ctree.c 52.2 KB
Newer Older
1
#include <linux/module.h>
2 3
#include "ctree.h"
#include "disk-io.h"
4
#include "transaction.h"
5

6 7 8
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, int level);
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
9 10
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size);
11
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
12
			  *root, struct buffer_head *dst, struct buffer_head
13 14
			  *src);
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
15 16
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf);
17 18
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot);
19

C
Chris Mason 已提交
20
inline void btrfs_init_path(struct btrfs_path *p)
C
Chris Mason 已提交
21
{
C
Chris Mason 已提交
22
	memset(p, 0, sizeof(*p));
C
Chris Mason 已提交
23 24
}

C
Chris Mason 已提交
25
struct btrfs_path *btrfs_alloc_path(void)
C
Chris Mason 已提交
26
{
C
Chris Mason 已提交
27 28 29 30 31
	struct btrfs_path *path;
	path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
	if (path)
		btrfs_init_path(path);
	return path;
C
Chris Mason 已提交
32 33
}

C
Chris Mason 已提交
34
void btrfs_free_path(struct btrfs_path *p)
35
{
C
Chris Mason 已提交
36 37
	btrfs_release_path(NULL, p);
	kmem_cache_free(btrfs_path_cachep, p);
38 39
}

C
Chris Mason 已提交
40
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
41 42
{
	int i;
C
Chris Mason 已提交
43
	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
44 45
		if (!p->nodes[i])
			break;
C
Chris Mason 已提交
46
		btrfs_block_release(root, p->nodes[i]);
47
	}
C
Chris Mason 已提交
48
	memset(p, 0, sizeof(*p));
49 50
}

51
static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
52 53
			   *root, struct buffer_head *buf, struct buffer_head
			   *parent, int parent_slot, struct buffer_head
54
			   **cow_ret)
C
Chris Mason 已提交
55
{
C
Chris Mason 已提交
56 57
	struct buffer_head *cow;
	struct btrfs_node *cow_node;
C
Chris Mason 已提交
58

59 60
	if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
				    trans->transid) {
C
Chris Mason 已提交
61 62 63
		*cow_ret = buf;
		return 0;
	}
64
	cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr);
C
Chris Mason 已提交
65
	cow_node = btrfs_buffer_node(cow);
C
Chris Mason 已提交
66 67
	if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
		WARN_ON(1);
C
Chris Mason 已提交
68
	memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
69
	btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow));
70
	btrfs_set_header_generation(&cow_node->header, trans->transid);
71
	btrfs_set_header_owner(&cow_node->header, root->root_key.objectid);
72
	btrfs_inc_ref(trans, root, buf);
C
Chris Mason 已提交
73 74
	if (buf == root->node) {
		root->node = cow;
C
Chris Mason 已提交
75
		get_bh(cow);
C
Chris Mason 已提交
76
		if (buf != root->commit_root) {
77
			btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
78
		}
C
Chris Mason 已提交
79
		btrfs_block_release(root, buf);
C
Chris Mason 已提交
80
	} else {
C
Chris Mason 已提交
81
		btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
82
					bh_blocknr(cow));
C
Chris Mason 已提交
83
		btrfs_mark_buffer_dirty(parent);
84
		btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
85
	}
C
Chris Mason 已提交
86
	btrfs_block_release(root, buf);
C
Chris Mason 已提交
87
	mark_buffer_dirty(cow);
C
Chris Mason 已提交
88
	*cow_ret = cow;
C
Chris Mason 已提交
89 90 91
	return 0;
}

C
Chris Mason 已提交
92 93 94 95 96
/*
 * The leaf data grows from end-to-front in the node.
 * this returns the address of the start of the last item,
 * which is the stop of the leaf data stack
 */
C
Chris Mason 已提交
97 98
static inline unsigned int leaf_data_end(struct btrfs_root *root,
					 struct btrfs_leaf *leaf)
99
{
100
	u32 nr = btrfs_header_nritems(&leaf->header);
101
	if (nr == 0)
C
Chris Mason 已提交
102
		return BTRFS_LEAF_DATA_SIZE(root);
C
Chris Mason 已提交
103
	return btrfs_item_offset(leaf->items + nr - 1);
104 105
}

C
Chris Mason 已提交
106 107 108
/*
 * compare two keys in a memcmp fashion
 */
C
Chris Mason 已提交
109
static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
110
{
C
Chris Mason 已提交
111 112 113 114 115
	struct btrfs_key k1;

	btrfs_disk_key_to_cpu(&k1, disk);

	if (k1.objectid > k2->objectid)
116
		return 1;
C
Chris Mason 已提交
117
	if (k1.objectid < k2->objectid)
118
		return -1;
C
Chris Mason 已提交
119 120 121 122
	if (k1.flags > k2->flags)
		return 1;
	if (k1.flags < k2->flags)
		return -1;
123 124 125 126
	if (k1.offset > k2->offset)
		return 1;
	if (k1.offset < k2->offset)
		return -1;
127 128
	return 0;
}
C
Chris Mason 已提交
129

C
Chris Mason 已提交
130 131
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
132
{
C
Chris Mason 已提交
133
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
134
	struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
C
Chris Mason 已提交
135
	int parent_slot;
136 137
	int slot;
	struct btrfs_key cpukey;
138
	u32 nritems = btrfs_header_nritems(&node->header);
C
Chris Mason 已提交
139 140

	if (path->nodes[level + 1])
C
Chris Mason 已提交
141
		parent = btrfs_buffer_node(path->nodes[level + 1]);
C
Chris Mason 已提交
142
	parent_slot = path->slots[level + 1];
143
	slot = path->slots[level];
144 145
	BUG_ON(nritems == 0);
	if (parent) {
C
Chris Mason 已提交
146
		struct btrfs_disk_key *parent_key;
C
Chris Mason 已提交
147 148
		parent_key = &parent->ptrs[parent_slot].key;
		BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
C
Chris Mason 已提交
149
			      sizeof(struct btrfs_disk_key)));
150
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
151
		       btrfs_header_blocknr(&node->header));
C
Chris Mason 已提交
152
	}
C
Chris Mason 已提交
153
	BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
154 155 156 157 158 159 160
	if (slot != 0) {
		btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot - 1].key);
		BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) <= 0);
	}
	if (slot < nritems - 1) {
		btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot + 1].key);
		BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) >= 0);
C
Chris Mason 已提交
161 162 163 164
	}
	return 0;
}

C
Chris Mason 已提交
165 166
static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
167
{
C
Chris Mason 已提交
168
	struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
C
Chris Mason 已提交
169
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
170
	int parent_slot;
171 172 173
	int slot = path->slots[0];
	struct btrfs_key cpukey;

174
	u32 nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
175 176

	if (path->nodes[level + 1])
C
Chris Mason 已提交
177
		parent = btrfs_buffer_node(path->nodes[level + 1]);
C
Chris Mason 已提交
178
	parent_slot = path->slots[level + 1];
C
Chris Mason 已提交
179
	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
180 181 182 183 184

	if (nritems == 0)
		return 0;

	if (parent) {
C
Chris Mason 已提交
185
		struct btrfs_disk_key *parent_key;
C
Chris Mason 已提交
186
		parent_key = &parent->ptrs[parent_slot].key;
C
Chris Mason 已提交
187
		BUG_ON(memcmp(parent_key, &leaf->items[0].key,
C
Chris Mason 已提交
188
		       sizeof(struct btrfs_disk_key)));
189
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
190
		       btrfs_header_blocknr(&leaf->header));
C
Chris Mason 已提交
191
	}
192 193 194 195 196 197 198 199 200 201 202
	if (slot != 0) {
		btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot - 1].key);
		BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) <= 0);
		BUG_ON(btrfs_item_offset(leaf->items + slot - 1) !=
			btrfs_item_end(leaf->items + slot));
	}
	if (slot < nritems - 1) {
		btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot + 1].key);
		BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) >= 0);
		BUG_ON(btrfs_item_offset(leaf->items + slot) !=
			btrfs_item_end(leaf->items + slot + 1));
C
Chris Mason 已提交
203
	}
204 205
	BUG_ON(btrfs_item_offset(leaf->items) +
	       btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root));
C
Chris Mason 已提交
206 207 208
	return 0;
}

C
Chris Mason 已提交
209 210
static int check_block(struct btrfs_root *root, struct btrfs_path *path,
			int level)
C
Chris Mason 已提交
211
{
C
Chris Mason 已提交
212 213 214 215
	struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
	if (memcmp(node->header.fsid, root->fs_info->disk_super->fsid,
		   sizeof(node->header.fsid)))
		BUG();
C
Chris Mason 已提交
216
	if (level == 0)
C
Chris Mason 已提交
217 218
		return check_leaf(root, path, level);
	return check_node(root, path, level);
C
Chris Mason 已提交
219 220
}

C
Chris Mason 已提交
221 222 223 224 225 226 227 228 229
/*
 * search for key in the array p.  items p are item_size apart
 * and there are 'max' items in p
 * the slot in the array is returned via slot, and it points to
 * the place where you would insert key if it is not found in
 * the array.
 *
 * slot may point to max if the key is bigger than all of the keys
 */
C
Chris Mason 已提交
230
static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
231 232 233 234 235 236
		       int max, int *slot)
{
	int low = 0;
	int high = max;
	int mid;
	int ret;
C
Chris Mason 已提交
237
	struct btrfs_disk_key *tmp;
238 239 240

	while(low < high) {
		mid = (low + high) / 2;
C
Chris Mason 已提交
241
		tmp = (struct btrfs_disk_key *)(p + mid * item_size);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
		ret = comp_keys(tmp, key);

		if (ret < 0)
			low = mid + 1;
		else if (ret > 0)
			high = mid;
		else {
			*slot = mid;
			return 0;
		}
	}
	*slot = low;
	return 1;
}

C
Chris Mason 已提交
257 258 259 260
/*
 * simple bin_search frontend that does the right thing for
 * leaves vs nodes
 */
C
Chris Mason 已提交
261
static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
262
{
263
	if (btrfs_is_leaf(c)) {
C
Chris Mason 已提交
264
		struct btrfs_leaf *l = (struct btrfs_leaf *)c;
C
Chris Mason 已提交
265 266
		return generic_bin_search((void *)l->items,
					  sizeof(struct btrfs_item),
267 268
					  key, btrfs_header_nritems(&c->header),
					  slot);
269
	} else {
C
Chris Mason 已提交
270 271
		return generic_bin_search((void *)c->ptrs,
					  sizeof(struct btrfs_key_ptr),
272 273
					  key, btrfs_header_nritems(&c->header),
					  slot);
274 275 276 277
	}
	return -1;
}

C
Chris Mason 已提交
278 279
static struct buffer_head *read_node_slot(struct btrfs_root *root,
				   struct buffer_head *parent_buf,
280 281
				   int slot)
{
C
Chris Mason 已提交
282
	struct btrfs_node *node = btrfs_buffer_node(parent_buf);
283 284
	if (slot < 0)
		return NULL;
285
	if (slot >= btrfs_header_nritems(&node->header))
286
		return NULL;
287
	return read_tree_block(root, btrfs_node_blockptr(node, slot));
288 289
}

290 291
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
			 *root, struct btrfs_path *path, int level)
292
{
C
Chris Mason 已提交
293 294 295 296
	struct buffer_head *right_buf;
	struct buffer_head *mid_buf;
	struct buffer_head *left_buf;
	struct buffer_head *parent_buf = NULL;
C
Chris Mason 已提交
297 298 299 300
	struct btrfs_node *right = NULL;
	struct btrfs_node *mid;
	struct btrfs_node *left = NULL;
	struct btrfs_node *parent = NULL;
301 302 303 304
	int ret = 0;
	int wret;
	int pslot;
	int orig_slot = path->slots[level];
305
	u64 orig_ptr;
306 307 308 309 310

	if (level == 0)
		return 0;

	mid_buf = path->nodes[level];
C
Chris Mason 已提交
311
	mid = btrfs_buffer_node(mid_buf);
312
	orig_ptr = btrfs_node_blockptr(mid, orig_slot);
313

C
Chris Mason 已提交
314
	if (level < BTRFS_MAX_LEVEL - 1)
315 316 317
		parent_buf = path->nodes[level + 1];
	pslot = path->slots[level + 1];

C
Chris Mason 已提交
318 319 320 321
	/*
	 * deal with the case where there is only one pointer in the root
	 * by promoting the node below to a root
	 */
322
	if (!parent_buf) {
C
Chris Mason 已提交
323
		struct buffer_head *child;
324
		u64 blocknr = bh_blocknr(mid_buf);
325

326
		if (btrfs_header_nritems(&mid->header) != 1)
327 328 329 330 331 332 333
			return 0;

		/* promote the child to a root */
		child = read_node_slot(root, mid_buf, 0);
		BUG_ON(!child);
		root->node = child;
		path->nodes[level] = NULL;
C
Chris Mason 已提交
334 335
		clean_tree_block(trans, root, mid_buf);
		wait_on_buffer(mid_buf);
336
		/* once for the path */
C
Chris Mason 已提交
337
		btrfs_block_release(root, mid_buf);
338
		/* once for the root ptr */
C
Chris Mason 已提交
339
		btrfs_block_release(root, mid_buf);
340
		return btrfs_free_extent(trans, root, blocknr, 1, 1);
341
	}
C
Chris Mason 已提交
342
	parent = btrfs_buffer_node(parent_buf);
343

C
Chris Mason 已提交
344 345
	if (btrfs_header_nritems(&mid->header) >
	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
346 347 348 349
		return 0;

	left_buf = read_node_slot(root, parent_buf, pslot - 1);
	right_buf = read_node_slot(root, parent_buf, pslot + 1);
350 351

	/* first, try to make some room in the middle buffer */
352
	if (left_buf) {
353 354
		btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1,
				&left_buf);
C
Chris Mason 已提交
355
		left = btrfs_buffer_node(left_buf);
356
		orig_slot += btrfs_header_nritems(&left->header);
357
		wret = push_node_left(trans, root, left_buf, mid_buf);
358 359
		if (wret < 0)
			ret = wret;
360
	}
361 362 363 364

	/*
	 * then try to empty the right most buffer into the middle
	 */
365
	if (right_buf) {
366 367
		btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1,
				&right_buf);
C
Chris Mason 已提交
368
		right = btrfs_buffer_node(right_buf);
369
		wret = push_node_left(trans, root, mid_buf, right_buf);
370 371
		if (wret < 0)
			ret = wret;
372
		if (btrfs_header_nritems(&right->header) == 0) {
373
			u64 blocknr = bh_blocknr(right_buf);
374
			clean_tree_block(trans, root, right_buf);
C
Chris Mason 已提交
375 376
			wait_on_buffer(right_buf);
			btrfs_block_release(root, right_buf);
377 378
			right_buf = NULL;
			right = NULL;
379 380
			wret = del_ptr(trans, root, path, level + 1, pslot +
				       1);
381 382
			if (wret)
				ret = wret;
383
			wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
384 385 386
			if (wret)
				ret = wret;
		} else {
C
Chris Mason 已提交
387 388 389 390 391
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot + 1].key,
				     &right->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
392 393
		}
	}
394
	if (btrfs_header_nritems(&mid->header) == 1) {
395 396 397 398 399 400 401 402 403 404
		/*
		 * we're not allowed to leave a node with one item in the
		 * tree during a delete.  A deletion from lower in the tree
		 * could try to delete the only pointer in this node.
		 * So, pull some keys from the left.
		 * There has to be a left pointer at this point because
		 * otherwise we would have pulled some pointers from the
		 * right
		 */
		BUG_ON(!left_buf);
405
		wret = balance_node_right(trans, root, mid_buf, left_buf);
406 407 408 409
		if (wret < 0)
			ret = wret;
		BUG_ON(wret == 1);
	}
410
	if (btrfs_header_nritems(&mid->header) == 0) {
411
		/* we've managed to empty the middle node, drop it */
412
		u64 blocknr = bh_blocknr(mid_buf);
413
		clean_tree_block(trans, root, mid_buf);
C
Chris Mason 已提交
414 415
		wait_on_buffer(mid_buf);
		btrfs_block_release(root, mid_buf);
416 417
		mid_buf = NULL;
		mid = NULL;
418
		wret = del_ptr(trans, root, path, level + 1, pslot);
419 420
		if (wret)
			ret = wret;
421
		wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
422 423
		if (wret)
			ret = wret;
424 425
	} else {
		/* update the parent key to reflect our changes */
C
Chris Mason 已提交
426 427 428 429
		btrfs_memcpy(root, parent,
			     &parent->ptrs[pslot].key, &mid->ptrs[0].key,
			     sizeof(struct btrfs_disk_key));
		btrfs_mark_buffer_dirty(parent_buf);
430
	}
431

432
	/* update the path */
433
	if (left_buf) {
434
		if (btrfs_header_nritems(&left->header) > orig_slot) {
C
Chris Mason 已提交
435
			get_bh(left_buf);
436 437 438 439
			path->nodes[level] = left_buf;
			path->slots[level + 1] -= 1;
			path->slots[level] = orig_slot;
			if (mid_buf)
C
Chris Mason 已提交
440
				btrfs_block_release(root, mid_buf);
441
		} else {
442
			orig_slot -= btrfs_header_nritems(&left->header);
443 444 445
			path->slots[level] = orig_slot;
		}
	}
446
	/* double check we haven't messed things up */
C
Chris Mason 已提交
447
	check_block(root, path, level);
C
Chris Mason 已提交
448 449 450
	if (orig_ptr !=
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
				path->slots[level]))
451
		BUG();
452 453

	if (right_buf)
C
Chris Mason 已提交
454
		btrfs_block_release(root, right_buf);
455
	if (left_buf)
C
Chris Mason 已提交
456
		btrfs_block_release(root, left_buf);
457 458 459
	return ret;
}

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
/* returns zero if the push worked, non-zero otherwise */
static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
				struct btrfs_root *root,
				struct btrfs_path *path, int level)
{
	struct buffer_head *right_buf;
	struct buffer_head *mid_buf;
	struct buffer_head *left_buf;
	struct buffer_head *parent_buf = NULL;
	struct btrfs_node *right = NULL;
	struct btrfs_node *mid;
	struct btrfs_node *left = NULL;
	struct btrfs_node *parent = NULL;
	int ret = 0;
	int wret;
	int pslot;
	int orig_slot = path->slots[level];
	u64 orig_ptr;

	if (level == 0)
		return 1;

	mid_buf = path->nodes[level];
	mid = btrfs_buffer_node(mid_buf);
	orig_ptr = btrfs_node_blockptr(mid, orig_slot);

	if (level < BTRFS_MAX_LEVEL - 1)
		parent_buf = path->nodes[level + 1];
	pslot = path->slots[level + 1];

	if (!parent_buf)
		return 1;
	parent = btrfs_buffer_node(parent_buf);

	left_buf = read_node_slot(root, parent_buf, pslot - 1);

	/* first, try to make some room in the middle buffer */
	if (left_buf) {
		u32 left_nr;
		left = btrfs_buffer_node(left_buf);
		left_nr = btrfs_header_nritems(&left->header);
C
Chris Mason 已提交
501 502 503 504 505 506 507 508
		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
			btrfs_cow_block(trans, root, left_buf, parent_buf,
					pslot - 1, &left_buf);
			left = btrfs_buffer_node(left_buf);
			wret = push_node_left(trans, root, left_buf, mid_buf);
		}
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
		if (wret < 0)
			ret = wret;
		if (wret == 0) {
			orig_slot += left_nr;
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot].key,
				     &mid->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
			if (btrfs_header_nritems(&left->header) > orig_slot) {
				path->nodes[level] = left_buf;
				path->slots[level + 1] -= 1;
				path->slots[level] = orig_slot;
				btrfs_block_release(root, mid_buf);
			} else {
				orig_slot -=
					btrfs_header_nritems(&left->header);
				path->slots[level] = orig_slot;
				btrfs_block_release(root, left_buf);
			}
			check_node(root, path, level);
			return 0;
		}
		btrfs_block_release(root, left_buf);
	}
	right_buf = read_node_slot(root, parent_buf, pslot + 1);

	/*
	 * then try to empty the right most buffer into the middle
	 */
	if (right_buf) {
C
Chris Mason 已提交
540
		u32 right_nr;
541
		right = btrfs_buffer_node(right_buf);
C
Chris Mason 已提交
542 543 544 545 546 547 548 549 550 551
		right_nr = btrfs_header_nritems(&right->header);
		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
			btrfs_cow_block(trans, root, right_buf,
					parent_buf, pslot + 1, &right_buf);
			right = btrfs_buffer_node(right_buf);
			wret = balance_node_right(trans, root,
						  right_buf, mid_buf);
		}
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
		if (wret < 0)
			ret = wret;
		if (wret == 0) {
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot + 1].key,
				     &right->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
			if (btrfs_header_nritems(&mid->header) <= orig_slot) {
				path->nodes[level] = right_buf;
				path->slots[level + 1] += 1;
				path->slots[level] = orig_slot -
					btrfs_header_nritems(&mid->header);
				btrfs_block_release(root, mid_buf);
			} else {
				btrfs_block_release(root, right_buf);
			}
			check_node(root, path, level);
			return 0;
		}
		btrfs_block_release(root, right_buf);
	}
	check_node(root, path, level);
	return 1;
}

C
Chris Mason 已提交
578 579 580 581 582 583
/*
 * look for key in the tree.  path is filled in with nodes along the way
 * if key is found, we return zero and you can find the item in the leaf
 * level of the path (level 0)
 *
 * If the key isn't found, the path points to the slot where it should
C
Chris Mason 已提交
584 585
 * be inserted, and 1 is returned.  If there are other errors during the
 * search a negative error number is returned.
C
Chris Mason 已提交
586 587 588 589
 *
 * if ins_len > 0, nodes and leaves will be split as we walk down the
 * tree.  if ins_len < 0, nodes will be merged as we walk down the tree (if
 * possible)
C
Chris Mason 已提交
590
 */
591 592 593
int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *key, struct btrfs_path *p, int
		      ins_len, int cow)
594
{
C
Chris Mason 已提交
595 596
	struct buffer_head *b;
	struct buffer_head *cow_buf;
C
Chris Mason 已提交
597
	struct btrfs_node *c;
598 599 600
	int slot;
	int ret;
	int level;
C
Chris Mason 已提交
601

C
Chris Mason 已提交
602 603
	WARN_ON(p->nodes[0] != NULL);
	WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
604 605
again:
	b = root->node;
C
Chris Mason 已提交
606
	get_bh(b);
607
	while (b) {
C
Chris Mason 已提交
608 609
		c = btrfs_buffer_node(b);
		level = btrfs_header_level(&c->header);
C
Chris Mason 已提交
610 611
		if (cow) {
			int wret;
C
Chris Mason 已提交
612 613 614
			wret = btrfs_cow_block(trans, root, b,
					       p->nodes[level + 1],
					       p->slots[level + 1],
615
					       &cow_buf);
C
Chris Mason 已提交
616
			b = cow_buf;
C
Chris Mason 已提交
617
			c = btrfs_buffer_node(b);
C
Chris Mason 已提交
618 619
		}
		BUG_ON(!cow && ins_len);
C
Chris Mason 已提交
620 621 622
		if (level != btrfs_header_level(&c->header))
			WARN_ON(1);
		level = btrfs_header_level(&c->header);
623
		p->nodes[level] = b;
C
Chris Mason 已提交
624
		ret = check_block(root, p, level);
C
Chris Mason 已提交
625 626
		if (ret)
			return -1;
627
		ret = bin_search(c, key, &slot);
628
		if (!btrfs_is_leaf(c)) {
629 630 631
			if (ret && slot > 0)
				slot -= 1;
			p->slots[level] = slot;
632 633
			if (ins_len > 0 && btrfs_header_nritems(&c->header) >=
			    BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
634
				int sret = split_node(trans, root, p, level);
C
Chris Mason 已提交
635 636 637 638
				BUG_ON(sret > 0);
				if (sret)
					return sret;
				b = p->nodes[level];
C
Chris Mason 已提交
639
				c = btrfs_buffer_node(b);
C
Chris Mason 已提交
640
				slot = p->slots[level];
641
			} else if (ins_len < 0) {
642 643
				int sret = balance_level(trans, root, p,
							 level);
644 645 646 647 648
				if (sret)
					return sret;
				b = p->nodes[level];
				if (!b)
					goto again;
C
Chris Mason 已提交
649
				c = btrfs_buffer_node(b);
650
				slot = p->slots[level];
651
				BUG_ON(btrfs_header_nritems(&c->header) == 1);
C
Chris Mason 已提交
652
			}
653
			b = read_tree_block(root, btrfs_node_blockptr(c, slot));
654
		} else {
C
Chris Mason 已提交
655
			struct btrfs_leaf *l = (struct btrfs_leaf *)c;
656
			p->slots[level] = slot;
C
Chris Mason 已提交
657
			if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
C
Chris Mason 已提交
658
			    sizeof(struct btrfs_item) + ins_len) {
659 660
				int sret = split_leaf(trans, root, key,
						      p, ins_len);
C
Chris Mason 已提交
661 662 663 664
				BUG_ON(sret > 0);
				if (sret)
					return sret;
			}
665 666 667
			return ret;
		}
	}
C
Chris Mason 已提交
668
	return 1;
669 670
}

C
Chris Mason 已提交
671 672 673 674 675 676
/*
 * adjust the pointers going up the tree, starting at level
 * making sure the right key of each node is points to 'key'.
 * This is used after shifting pointers to the left, so it stops
 * fixing up pointers when a given leaf/node is not in slot 0 of the
 * higher levels
C
Chris Mason 已提交
677 678 679
 *
 * If this fails to write a tree block, it returns -1, but continues
 * fixing up the blocks in ram so the tree is consistent.
C
Chris Mason 已提交
680
 */
681 682 683
static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, struct btrfs_disk_key
			  *key, int level)
684 685
{
	int i;
C
Chris Mason 已提交
686
	int ret = 0;
C
Chris Mason 已提交
687 688
	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
		struct btrfs_node *t;
689
		int tslot = path->slots[i];
690
		if (!path->nodes[i])
691
			break;
C
Chris Mason 已提交
692
		t = btrfs_buffer_node(path->nodes[i]);
C
Chris Mason 已提交
693 694
		btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
		btrfs_mark_buffer_dirty(path->nodes[i]);
695 696 697
		if (tslot != 0)
			break;
	}
C
Chris Mason 已提交
698
	return ret;
699 700
}

C
Chris Mason 已提交
701 702
/*
 * try to push data from one node into the next node left in the
703
 * tree.
C
Chris Mason 已提交
704 705 706
 *
 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
 * error, and > 0 if there was no room in the left hand block.
C
Chris Mason 已提交
707
 */
708
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
709 710
			  *root, struct buffer_head *dst_buf, struct
			  buffer_head *src_buf)
711
{
C
Chris Mason 已提交
712 713
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
714
	int push_items = 0;
715 716
	int src_nritems;
	int dst_nritems;
C
Chris Mason 已提交
717
	int ret = 0;
718

719 720
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
721
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
722
	if (push_items <= 0) {
723
		return 1;
724
	}
725

726
	if (src_nritems < push_items)
727 728
		push_items = src_nritems;

C
Chris Mason 已提交
729 730
	btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
		     push_items * sizeof(struct btrfs_key_ptr));
731
	if (push_items < src_nritems) {
C
Chris Mason 已提交
732
		btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
C
Chris Mason 已提交
733
			(src_nritems - push_items) *
C
Chris Mason 已提交
734
			sizeof(struct btrfs_key_ptr));
735
	}
736 737
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
C
Chris Mason 已提交
738 739
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
740 741 742 743 744 745 746 747 748 749 750 751
	return ret;
}

/*
 * try to push data from one node into the next node right in the
 * tree.
 *
 * returns 0 if some ptrs were pushed, < 0 if there was some horrible
 * error, and > 0 if there was no room in the right hand block.
 *
 * this will  only push up to 1/2 the contents of the left node over
 */
752
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
753 754
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf)
755
{
C
Chris Mason 已提交
756 757
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
758 759 760 761 762 763
	int push_items = 0;
	int max_push;
	int src_nritems;
	int dst_nritems;
	int ret = 0;

764 765
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
766
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
767 768 769 770 771 772 773 774 775 776 777
	if (push_items <= 0) {
		return 1;
	}

	max_push = src_nritems / 2 + 1;
	/* don't try to empty the node */
	if (max_push > src_nritems)
		return 1;
	if (max_push < push_items)
		push_items = max_push;

C
Chris Mason 已提交
778 779 780 781 782 783
	btrfs_memmove(root, dst, dst->ptrs + push_items, dst->ptrs,
		      dst_nritems * sizeof(struct btrfs_key_ptr));

	btrfs_memcpy(root, dst, dst->ptrs,
		     src->ptrs + src_nritems - push_items,
		     push_items * sizeof(struct btrfs_key_ptr));
784

785 786
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
787

C
Chris Mason 已提交
788 789
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
C
Chris Mason 已提交
790
	return ret;
791 792
}

C
Chris Mason 已提交
793 794 795 796
/*
 * helper function to insert a new root level in the tree.
 * A new node is allocated, and a single item is inserted to
 * point to the existing root
C
Chris Mason 已提交
797 798
 *
 * returns zero on success or < 0 on failure.
C
Chris Mason 已提交
799
 */
800 801
static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int level)
C
Chris Mason 已提交
802
{
C
Chris Mason 已提交
803
	struct buffer_head *t;
C
Chris Mason 已提交
804 805
	struct btrfs_node *lower;
	struct btrfs_node *c;
C
Chris Mason 已提交
806
	struct btrfs_disk_key *lower_key;
C
Chris Mason 已提交
807 808 809 810

	BUG_ON(path->nodes[level]);
	BUG_ON(path->nodes[level-1] != root->node);

811
	t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr);
C
Chris Mason 已提交
812
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
813
	memset(c, 0, root->blocksize);
814 815
	btrfs_set_header_nritems(&c->header, 1);
	btrfs_set_header_level(&c->header, level);
816
	btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
817
	btrfs_set_header_generation(&c->header, trans->transid);
818
	btrfs_set_header_owner(&c->header, root->root_key.objectid);
C
Chris Mason 已提交
819
	lower = btrfs_buffer_node(path->nodes[level-1]);
C
Chris Mason 已提交
820 821
	memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(c->header.fsid));
822
	if (btrfs_is_leaf(lower))
C
Chris Mason 已提交
823
		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
C
Chris Mason 已提交
824
	else
C
Chris Mason 已提交
825
		lower_key = &lower->ptrs[0].key;
C
Chris Mason 已提交
826 827
	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
		     sizeof(struct btrfs_disk_key));
828
	btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
829

C
Chris Mason 已提交
830
	btrfs_mark_buffer_dirty(t);
831

C
Chris Mason 已提交
832
	/* the super has an extra ref to root->node */
C
Chris Mason 已提交
833
	btrfs_block_release(root, root->node);
C
Chris Mason 已提交
834
	root->node = t;
C
Chris Mason 已提交
835
	get_bh(t);
C
Chris Mason 已提交
836 837 838 839 840
	path->nodes[level] = t;
	path->slots[level] = 0;
	return 0;
}

C
Chris Mason 已提交
841 842 843
/*
 * worker function to insert a single pointer in a node.
 * the node should have enough room for the pointer already
C
Chris Mason 已提交
844
 *
C
Chris Mason 已提交
845 846
 * slot and level indicate where you want the key to go, and
 * blocknr is the block the key points to.
C
Chris Mason 已提交
847 848
 *
 * returns zero on success and < 0 on any error
C
Chris Mason 已提交
849
 */
850 851 852
static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, struct btrfs_disk_key
		      *key, u64 blocknr, int slot, int level)
C
Chris Mason 已提交
853
{
C
Chris Mason 已提交
854
	struct btrfs_node *lower;
C
Chris Mason 已提交
855
	int nritems;
C
Chris Mason 已提交
856 857

	BUG_ON(!path->nodes[level]);
C
Chris Mason 已提交
858
	lower = btrfs_buffer_node(path->nodes[level]);
859
	nritems = btrfs_header_nritems(&lower->header);
C
Chris Mason 已提交
860 861
	if (slot > nritems)
		BUG();
C
Chris Mason 已提交
862
	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
C
Chris Mason 已提交
863 864
		BUG();
	if (slot != nritems) {
C
Chris Mason 已提交
865 866 867
		btrfs_memmove(root, lower, lower->ptrs + slot + 1,
			      lower->ptrs + slot,
			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
C
Chris Mason 已提交
868
	}
C
Chris Mason 已提交
869 870
	btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
		     key, sizeof(struct btrfs_disk_key));
871
	btrfs_set_node_blockptr(lower, slot, blocknr);
872
	btrfs_set_header_nritems(&lower->header, nritems + 1);
C
Chris Mason 已提交
873
	btrfs_mark_buffer_dirty(path->nodes[level]);
874
	check_node(root, path, level);
C
Chris Mason 已提交
875 876 877
	return 0;
}

C
Chris Mason 已提交
878 879 880 881 882 883
/*
 * split the node at the specified level in path in two.
 * The path is corrected to point to the appropriate node after the split
 *
 * Before splitting this tries to make some room in the node by pushing
 * left and right, if either one works, it returns right away.
C
Chris Mason 已提交
884 885
 *
 * returns 0 on success and < 0 on failure
C
Chris Mason 已提交
886
 */
887 888
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, int level)
889
{
C
Chris Mason 已提交
890
	struct buffer_head *t;
C
Chris Mason 已提交
891
	struct btrfs_node *c;
C
Chris Mason 已提交
892
	struct buffer_head *split_buffer;
C
Chris Mason 已提交
893
	struct btrfs_node *split;
894
	int mid;
C
Chris Mason 已提交
895
	int ret;
C
Chris Mason 已提交
896
	int wret;
897
	u32 c_nritems;
898

C
Chris Mason 已提交
899
	t = path->nodes[level];
C
Chris Mason 已提交
900
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
901 902
	if (t == root->node) {
		/* trying to split the root, lets make a new one */
903
		ret = insert_new_root(trans, root, path, level + 1);
C
Chris Mason 已提交
904 905
		if (ret)
			return ret;
906 907 908 909 910 911 912 913
	} else {
		ret = push_nodes_for_insert(trans, root, path, level);
		t = path->nodes[level];
		c = btrfs_buffer_node(t);
		if (!ret &&
		    btrfs_header_nritems(&c->header) <
		    BTRFS_NODEPTRS_PER_BLOCK(root) - 1)
			return 0;
914
	}
915

916
	c_nritems = btrfs_header_nritems(&c->header);
917
	split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr);
C
Chris Mason 已提交
918
	split = btrfs_buffer_node(split_buffer);
919
	btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
920
	btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
921
	btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer));
922
	btrfs_set_header_generation(&split->header, trans->transid);
923
	btrfs_set_header_owner(&split->header, root->root_key.objectid);
C
Chris Mason 已提交
924 925
	memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(split->header.fsid));
926
	mid = (c_nritems + 1) / 2;
C
Chris Mason 已提交
927 928
	btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
		     (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
929 930
	btrfs_set_header_nritems(&split->header, c_nritems - mid);
	btrfs_set_header_nritems(&c->header, mid);
C
Chris Mason 已提交
931 932
	ret = 0;

C
Chris Mason 已提交
933 934
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(split_buffer);
935
	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
936
			  bh_blocknr(split_buffer), path->slots[level + 1] + 1,
C
Chris Mason 已提交
937
			  level + 1);
C
Chris Mason 已提交
938 939 940
	if (wret)
		ret = wret;

C
Chris Mason 已提交
941
	if (path->slots[level] >= mid) {
C
Chris Mason 已提交
942
		path->slots[level] -= mid;
C
Chris Mason 已提交
943
		btrfs_block_release(root, t);
C
Chris Mason 已提交
944 945 946
		path->nodes[level] = split_buffer;
		path->slots[level + 1] += 1;
	} else {
C
Chris Mason 已提交
947
		btrfs_block_release(root, split_buffer);
948
	}
C
Chris Mason 已提交
949
	return ret;
950 951
}

C
Chris Mason 已提交
952 953 954 955 956
/*
 * how many bytes are required to store the items in a leaf.  start
 * and nr indicate which items in the leaf to check.  This totals up the
 * space used both by the item structs and the item data
 */
C
Chris Mason 已提交
957
static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
958 959
{
	int data_len;
960 961
	int nritems = btrfs_header_nritems(&l->header);
	int end = min(nritems, start + nr) - 1;
962 963 964

	if (!nr)
		return 0;
C
Chris Mason 已提交
965 966 967
	data_len = btrfs_item_end(l->items + start);
	data_len = data_len - btrfs_item_offset(l->items + end);
	data_len += sizeof(struct btrfs_item) * nr;
968
	WARN_ON(data_len < 0);
969 970 971
	return data_len;
}

972 973 974 975 976 977 978 979 980 981 982
/*
 * The space between the end of the leaf items and
 * the start of the leaf data.  IOW, how much room
 * the leaf has left for both items and data
 */
int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf)
{
	int nritems = btrfs_header_nritems(&leaf->header);
	return BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
}

C
Chris Mason 已提交
983 984 985
/*
 * push some data in the path leaf to the right, trying to free up at
 * least data_size bytes.  returns zero if the push worked, nonzero otherwise
C
Chris Mason 已提交
986 987 988
 *
 * returns 1 if the push failed because the other node didn't have enough
 * room, 0 if everything worked out and < 0 if there were major errors.
C
Chris Mason 已提交
989
 */
990 991
static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int data_size)
C
Chris Mason 已提交
992
{
C
Chris Mason 已提交
993 994
	struct buffer_head *left_buf = path->nodes[0];
	struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
C
Chris Mason 已提交
995
	struct btrfs_leaf *right;
C
Chris Mason 已提交
996 997 998
	struct buffer_head *right_buf;
	struct buffer_head *upper;
	struct btrfs_node *upper_node;
C
Chris Mason 已提交
999 1000 1001 1002 1003
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1004
	struct btrfs_item *item;
1005 1006
	u32 left_nritems;
	u32 right_nritems;
C
Chris Mason 已提交
1007 1008 1009 1010 1011 1012

	slot = path->slots[1];
	if (!path->nodes[1]) {
		return 1;
	}
	upper = path->nodes[1];
C
Chris Mason 已提交
1013 1014
	upper_node = btrfs_buffer_node(upper);
	if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
C
Chris Mason 已提交
1015 1016
		return 1;
	}
C
Chris Mason 已提交
1017 1018 1019
	right_buf = read_tree_block(root,
		    btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1020
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1021
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1022
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1023 1024
		return 1;
	}
C
Chris Mason 已提交
1025
	/* cow and double check */
1026
	btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf);
C
Chris Mason 已提交
1027
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1028
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1029
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1030
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1031 1032 1033
		return 1;
	}

1034
	left_nritems = btrfs_header_nritems(&left->header);
1035 1036 1037 1038 1039
	if (left_nritems == 0) {
		btrfs_block_release(root, right_buf);
		return 1;
	}
	for (i = left_nritems - 1; i >= 1; i--) {
C
Chris Mason 已提交
1040 1041 1042
		item = left->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1043 1044
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
C
Chris Mason 已提交
1045 1046
			break;
		push_items++;
C
Chris Mason 已提交
1047
		push_space += btrfs_item_size(item) + sizeof(*item);
C
Chris Mason 已提交
1048 1049
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1050
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1051 1052
		return 1;
	}
1053 1054
	if (push_items == left_nritems)
		WARN_ON(1);
1055
	right_nritems = btrfs_header_nritems(&right->header);
C
Chris Mason 已提交
1056
	/* push left to right */
C
Chris Mason 已提交
1057
	push_space = btrfs_item_end(left->items + left_nritems - push_items);
C
Chris Mason 已提交
1058
	push_space -= leaf_data_end(root, left);
C
Chris Mason 已提交
1059
	/* make room in the right data area */
C
Chris Mason 已提交
1060 1061 1062 1063 1064
	btrfs_memmove(root, right, btrfs_leaf_data(right) +
		      leaf_data_end(root, right) - push_space,
		      btrfs_leaf_data(right) +
		      leaf_data_end(root, right), BTRFS_LEAF_DATA_SIZE(root) -
		      leaf_data_end(root, right));
C
Chris Mason 已提交
1065
	/* copy from the left data area */
C
Chris Mason 已提交
1066 1067 1068 1069 1070
	btrfs_memcpy(root, right, btrfs_leaf_data(right) +
		     BTRFS_LEAF_DATA_SIZE(root) - push_space,
		     btrfs_leaf_data(left) + leaf_data_end(root, left),
		     push_space);
	btrfs_memmove(root, right, right->items + push_items, right->items,
C
Chris Mason 已提交
1071
		right_nritems * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1072
	/* copy the items from left to right */
C
Chris Mason 已提交
1073 1074 1075
	btrfs_memcpy(root, right, right->items, left->items +
		     left_nritems - push_items,
		     push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1076 1077

	/* update the item pointers */
1078 1079
	right_nritems += push_items;
	btrfs_set_header_nritems(&right->header, right_nritems);
C
Chris Mason 已提交
1080
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1081
	for (i = 0; i < right_nritems; i++) {
C
Chris Mason 已提交
1082 1083 1084
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1085
	}
1086 1087
	left_nritems -= push_items;
	btrfs_set_header_nritems(&left->header, left_nritems);
C
Chris Mason 已提交
1088

C
Chris Mason 已提交
1089 1090
	btrfs_mark_buffer_dirty(left_buf);
	btrfs_mark_buffer_dirty(right_buf);
1091

C
Chris Mason 已提交
1092
	btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key,
C
Chris Mason 已提交
1093
		&right->items[0].key, sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1094
	btrfs_mark_buffer_dirty(upper);
C
Chris Mason 已提交
1095

C
Chris Mason 已提交
1096
	/* then fixup the leaf pointer in the path */
1097 1098
	if (path->slots[0] >= left_nritems) {
		path->slots[0] -= left_nritems;
C
Chris Mason 已提交
1099
		btrfs_block_release(root, path->nodes[0]);
C
Chris Mason 已提交
1100 1101 1102
		path->nodes[0] = right_buf;
		path->slots[1] += 1;
	} else {
C
Chris Mason 已提交
1103
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1104
	}
1105 1106
	if (path->nodes[1])
		check_node(root, path, 1);
C
Chris Mason 已提交
1107 1108
	return 0;
}
C
Chris Mason 已提交
1109 1110 1111 1112
/*
 * push some data in the path leaf to the left, trying to free up at
 * least data_size bytes.  returns zero if the push worked, nonzero otherwise
 */
1113 1114
static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int data_size)
1115
{
C
Chris Mason 已提交
1116 1117 1118
	struct buffer_head *right_buf = path->nodes[0];
	struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
	struct buffer_head *t;
C
Chris Mason 已提交
1119
	struct btrfs_leaf *left;
1120 1121 1122 1123 1124
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1125
	struct btrfs_item *item;
1126
	u32 old_left_nritems;
C
Chris Mason 已提交
1127 1128
	int ret = 0;
	int wret;
1129 1130 1131 1132 1133 1134 1135 1136

	slot = path->slots[1];
	if (slot == 0) {
		return 1;
	}
	if (!path->nodes[1]) {
		return 1;
	}
C
Chris Mason 已提交
1137 1138 1139
	t = read_tree_block(root,
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1140
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1141
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1142
		btrfs_block_release(root, t);
1143 1144
		return 1;
	}
C
Chris Mason 已提交
1145 1146

	/* cow and double check */
1147
	btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
C
Chris Mason 已提交
1148
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1149
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1150
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1151
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1152 1153 1154
		return 1;
	}

1155 1156 1157 1158 1159 1160
	if (btrfs_header_nritems(&right->header) == 0) {
		btrfs_block_release(root, t);
		return 1;
	}

	for (i = 0; i < btrfs_header_nritems(&right->header) - 1; i++) {
1161 1162 1163
		item = right->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1164 1165
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
1166 1167
			break;
		push_items++;
C
Chris Mason 已提交
1168
		push_space += btrfs_item_size(item) + sizeof(*item);
1169 1170
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1171
		btrfs_block_release(root, t);
1172 1173
		return 1;
	}
1174 1175
	if (push_items == btrfs_header_nritems(&right->header))
		WARN_ON(1);
1176
	/* push data from right to left */
C
Chris Mason 已提交
1177 1178 1179
	btrfs_memcpy(root, left, left->items +
		     btrfs_header_nritems(&left->header),
		     right->items, push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1180
	push_space = BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1181
		     btrfs_item_offset(right->items + push_items -1);
C
Chris Mason 已提交
1182 1183 1184 1185 1186
	btrfs_memcpy(root, left, btrfs_leaf_data(left) +
		     leaf_data_end(root, left) - push_space,
		     btrfs_leaf_data(right) +
		     btrfs_item_offset(right->items + push_items - 1),
		     push_space);
1187
	old_left_nritems = btrfs_header_nritems(&left->header);
1188 1189
	BUG_ON(old_left_nritems < 0);

C
Chris Mason 已提交
1190
	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
C
Chris Mason 已提交
1191 1192 1193
		u32 ioff = btrfs_item_offset(left->items + i);
		btrfs_set_item_offset(left->items + i, ioff -
				     (BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1194 1195
				      btrfs_item_offset(left->items +
						        old_left_nritems - 1)));
1196
	}
1197
	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1198 1199

	/* fixup right node */
C
Chris Mason 已提交
1200
	push_space = btrfs_item_offset(right->items + push_items - 1) -
C
Chris Mason 已提交
1201
		     leaf_data_end(root, right);
C
Chris Mason 已提交
1202 1203 1204 1205 1206
	btrfs_memmove(root, right, btrfs_leaf_data(right) +
		      BTRFS_LEAF_DATA_SIZE(root) - push_space,
		      btrfs_leaf_data(right) +
		      leaf_data_end(root, right), push_space);
	btrfs_memmove(root, right, right->items, right->items + push_items,
1207
		(btrfs_header_nritems(&right->header) - push_items) *
C
Chris Mason 已提交
1208
		sizeof(struct btrfs_item));
1209 1210 1211
	btrfs_set_header_nritems(&right->header,
				 btrfs_header_nritems(&right->header) -
				 push_items);
C
Chris Mason 已提交
1212
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1213

1214
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1215 1216 1217
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
1218
	}
1219

C
Chris Mason 已提交
1220 1221
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);
1222

1223
	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
C
Chris Mason 已提交
1224 1225
	if (wret)
		ret = wret;
1226 1227 1228 1229

	/* then fixup the leaf pointer in the path */
	if (path->slots[0] < push_items) {
		path->slots[0] += old_left_nritems;
C
Chris Mason 已提交
1230
		btrfs_block_release(root, path->nodes[0]);
1231
		path->nodes[0] = t;
1232 1233
		path->slots[1] -= 1;
	} else {
C
Chris Mason 已提交
1234
		btrfs_block_release(root, t);
1235 1236
		path->slots[0] -= push_items;
	}
1237
	BUG_ON(path->slots[0] < 0);
1238 1239
	if (path->nodes[1])
		check_node(root, path, 1);
C
Chris Mason 已提交
1240
	return ret;
1241 1242
}

C
Chris Mason 已提交
1243 1244 1245
/*
 * split the path's leaf in two, making sure there is at least data_size
 * available for the resulting leaf level of the path.
C
Chris Mason 已提交
1246 1247
 *
 * returns 0 if all went well and < 0 on failure.
C
Chris Mason 已提交
1248
 */
1249
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1250 1251
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size)
1252
{
C
Chris Mason 已提交
1253
	struct buffer_head *l_buf;
C
Chris Mason 已提交
1254
	struct btrfs_leaf *l;
1255
	u32 nritems;
1256 1257
	int mid;
	int slot;
C
Chris Mason 已提交
1258
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1259
	struct buffer_head *right_buffer;
C
Chris Mason 已提交
1260
	int space_needed = data_size + sizeof(struct btrfs_item);
1261 1262 1263
	int data_copy_size;
	int rt_data_off;
	int i;
1264
	int ret = 0;
C
Chris Mason 已提交
1265
	int wret;
1266 1267
	int double_split = 0;
	struct btrfs_disk_key disk_key;
C
Chris Mason 已提交
1268

C
Chris Mason 已提交
1269
	/* first try to make some room by pushing left and right */
1270
	wret = push_leaf_left(trans, root, path, data_size);
C
Chris Mason 已提交
1271 1272 1273
	if (wret < 0)
		return wret;
	if (wret) {
1274
		wret = push_leaf_right(trans, root, path, data_size);
C
Chris Mason 已提交
1275 1276 1277
		if (wret < 0)
			return wret;
	}
C
Chris Mason 已提交
1278
	l_buf = path->nodes[0];
C
Chris Mason 已提交
1279
	l = btrfs_buffer_leaf(l_buf);
C
Chris Mason 已提交
1280 1281

	/* did the pushes work? */
C
Chris Mason 已提交
1282 1283
	if (btrfs_leaf_free_space(root, l) >=
	    sizeof(struct btrfs_item) + data_size)
C
Chris Mason 已提交
1284 1285
		return 0;

C
Chris Mason 已提交
1286
	if (!path->nodes[1]) {
1287
		ret = insert_new_root(trans, root, path, 1);
C
Chris Mason 已提交
1288 1289 1290
		if (ret)
			return ret;
	}
1291
	slot = path->slots[0];
1292
	nritems = btrfs_header_nritems(&l->header);
1293
	mid = (nritems + 1)/ 2;
1294
	right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
1295
	BUG_ON(!right_buffer);
C
Chris Mason 已提交
1296
	right = btrfs_buffer_leaf(right_buffer);
C
Chris Mason 已提交
1297
	memset(&right->header, 0, sizeof(right->header));
1298
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1299
	btrfs_set_header_generation(&right->header, trans->transid);
1300
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1301
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1302 1303
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1304 1305 1306 1307 1308 1309 1310 1311 1312
	if (mid <= slot) {
		if (nritems == 1 ||
		    leaf_space_used(l, mid, nritems - mid) + space_needed >
			BTRFS_LEAF_DATA_SIZE(root)) {
			if (slot >= nritems) {
				btrfs_cpu_key_to_disk(&disk_key, ins_key);
				btrfs_set_header_nritems(&right->header, 0);
				wret = insert_ptr(trans, root, path,
						  &disk_key,
1313
						  bh_blocknr(right_buffer),
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
						  path->slots[1] + 1, 1);
				if (wret)
					ret = wret;
				btrfs_block_release(root, path->nodes[0]);
				path->nodes[0] = right_buffer;
				path->slots[0] = 0;
				path->slots[1] += 1;
				return ret;
			}
			mid = slot;
			double_split = 1;
		}
	} else {
		if (leaf_space_used(l, 0, mid + 1) + space_needed >
			BTRFS_LEAF_DATA_SIZE(root)) {
			if (slot == 0) {
				btrfs_cpu_key_to_disk(&disk_key, ins_key);
				btrfs_set_header_nritems(&right->header, 0);
				wret = insert_ptr(trans, root, path,
						  &disk_key,
1334
						  bh_blocknr(right_buffer),
1335
						  path->slots[1], 1);
1336 1337 1338 1339 1340
				if (wret)
					ret = wret;
				btrfs_block_release(root, path->nodes[0]);
				path->nodes[0] = right_buffer;
				path->slots[0] = 0;
1341 1342 1343 1344 1345 1346
				if (path->slots[1] == 0) {
					wret = fixup_low_keys(trans, root,
					           path, &disk_key, 1);
					if (wret)
						ret = wret;
				}
1347 1348 1349 1350 1351 1352 1353
				return ret;
			}
			mid = slot;
			double_split = 1;
		}
	}
	btrfs_set_header_nritems(&right->header, nritems - mid);
C
Chris Mason 已提交
1354 1355
	data_copy_size = btrfs_item_end(l->items + mid) -
			 leaf_data_end(root, l);
C
Chris Mason 已提交
1356 1357 1358 1359 1360 1361
	btrfs_memcpy(root, right, right->items, l->items + mid,
		     (nritems - mid) * sizeof(struct btrfs_item));
	btrfs_memcpy(root, right,
		     btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) -
		     data_copy_size, btrfs_leaf_data(l) +
		     leaf_data_end(root, l), data_copy_size);
C
Chris Mason 已提交
1362 1363
	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
		      btrfs_item_end(l->items + mid);
C
Chris Mason 已提交
1364

C
Chris Mason 已提交
1365
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1366
		u32 ioff = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1367 1368
		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
	}
C
Chris Mason 已提交
1369

1370
	btrfs_set_header_nritems(&l->header, mid);
C
Chris Mason 已提交
1371
	ret = 0;
1372
	wret = insert_ptr(trans, root, path, &right->items[0].key,
1373
			  bh_blocknr(right_buffer), path->slots[1] + 1, 1);
C
Chris Mason 已提交
1374 1375
	if (wret)
		ret = wret;
C
Chris Mason 已提交
1376 1377
	btrfs_mark_buffer_dirty(right_buffer);
	btrfs_mark_buffer_dirty(l_buf);
1378
	BUG_ON(path->slots[0] != slot);
1379
	if (mid <= slot) {
C
Chris Mason 已提交
1380
		btrfs_block_release(root, path->nodes[0]);
1381
		path->nodes[0] = right_buffer;
1382 1383
		path->slots[0] -= mid;
		path->slots[1] += 1;
1384
	} else
C
Chris Mason 已提交
1385
		btrfs_block_release(root, right_buffer);
1386
	BUG_ON(path->slots[0] < 0);
1387
	check_node(root, path, 1);
1388 1389 1390

	if (!double_split)
		return ret;
1391
	right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
1392 1393 1394
	BUG_ON(!right_buffer);
	right = btrfs_buffer_leaf(right_buffer);
	memset(&right->header, 0, sizeof(right->header));
1395
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1396
	btrfs_set_header_generation(&right->header, trans->transid);
1397
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1398
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1399 1400
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1401 1402 1403 1404
	btrfs_cpu_key_to_disk(&disk_key, ins_key);
	btrfs_set_header_nritems(&right->header, 0);
	wret = insert_ptr(trans, root, path,
			  &disk_key,
1405
			  bh_blocknr(right_buffer),
1406 1407 1408
			  path->slots[1], 1);
	if (wret)
		ret = wret;
1409 1410 1411 1412 1413
	if (path->slots[1] == 0) {
		wret = fixup_low_keys(trans, root, path, &disk_key, 1);
		if (wret)
			ret = wret;
	}
1414 1415 1416 1417 1418
	btrfs_block_release(root, path->nodes[0]);
	path->nodes[0] = right_buffer;
	path->slots[0] = 0;
	check_node(root, path, 1);
	check_leaf(root, path, 0);
1419 1420 1421
	return ret;
}

C
Chris Mason 已提交
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
int btrfs_truncate_item(struct btrfs_trans_handle *trans,
			struct btrfs_root *root,
			struct btrfs_path *path,
			u32 new_size)
{
	int ret = 0;
	int slot;
	int slot_orig;
	struct btrfs_leaf *leaf;
	struct buffer_head *leaf_buf;
	u32 nritems;
	unsigned int data_end;
	unsigned int old_data_start;
	unsigned int old_size;
	unsigned int size_diff;
	int i;

	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
	leaf = btrfs_buffer_leaf(leaf_buf);

	nritems = btrfs_header_nritems(&leaf->header);
	data_end = leaf_data_end(root, leaf);

	slot = path->slots[0];
	old_data_start = btrfs_item_offset(leaf->items + slot);
	old_size = btrfs_item_size(leaf->items + slot);
	BUG_ON(old_size <= new_size);
	size_diff = old_size - new_size;

	BUG_ON(slot < 0);
	BUG_ON(slot >= nritems);

	/*
	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
	 */
	/* first correct the data pointers */
	for (i = slot; i < nritems; i++) {
		u32 ioff = btrfs_item_offset(leaf->items + i);
		btrfs_set_item_offset(leaf->items + i,
				      ioff + size_diff);
	}
	/* shift the data */
	btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
		      data_end + size_diff, btrfs_leaf_data(leaf) +
		      data_end, old_data_start + new_size - data_end);
	btrfs_set_item_size(leaf->items + slot, new_size);
	btrfs_mark_buffer_dirty(leaf_buf);

	ret = 0;
	if (btrfs_leaf_free_space(root, leaf) < 0)
		BUG();
	check_leaf(root, path, 0);
	return ret;
}

1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, u32 data_size)
{
	int ret = 0;
	int slot;
	int slot_orig;
	struct btrfs_leaf *leaf;
	struct buffer_head *leaf_buf;
	u32 nritems;
	unsigned int data_end;
	unsigned int old_data;
	unsigned int old_size;
	int i;

	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
	leaf = btrfs_buffer_leaf(leaf_buf);

	nritems = btrfs_header_nritems(&leaf->header);
	data_end = leaf_data_end(root, leaf);

	if (btrfs_leaf_free_space(root, leaf) < data_size)
		BUG();
	slot = path->slots[0];
	old_data = btrfs_item_end(leaf->items + slot);

	BUG_ON(slot < 0);
	BUG_ON(slot >= nritems);

	/*
	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
	 */
	/* first correct the data pointers */
	for (i = slot; i < nritems; i++) {
		u32 ioff = btrfs_item_offset(leaf->items + i);
		btrfs_set_item_offset(leaf->items + i,
				      ioff - data_size);
	}
	/* shift the data */
	btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
		      data_end - data_size, btrfs_leaf_data(leaf) +
		      data_end, old_data - data_end);
	data_end = old_data;
	old_size = btrfs_item_size(leaf->items + slot);
	btrfs_set_item_size(leaf->items + slot, old_size + data_size);
	btrfs_mark_buffer_dirty(leaf_buf);

	ret = 0;
	if (btrfs_leaf_free_space(root, leaf) < 0)
		BUG();
	check_leaf(root, path, 0);
	return ret;
}

C
Chris Mason 已提交
1532 1533 1534 1535
/*
 * Given a key and some data, insert an item into the tree.
 * This does all the path init required, making room in the tree if needed.
 */
1536 1537 1538
int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
			    *root, struct btrfs_path *path, struct btrfs_key
			    *cpu_key, u32 data_size)
1539
{
C
Chris Mason 已提交
1540
	int ret = 0;
1541
	int slot;
1542
	int slot_orig;
C
Chris Mason 已提交
1543
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1544
	struct buffer_head *leaf_buf;
1545
	u32 nritems;
1546
	unsigned int data_end;
C
Chris Mason 已提交
1547 1548 1549
	struct btrfs_disk_key disk_key;

	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1550

C
Chris Mason 已提交
1551
	/* create a root if there isn't one */
C
Chris Mason 已提交
1552
	if (!root->node)
C
Chris Mason 已提交
1553
		BUG();
1554
	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1555
	if (ret == 0) {
1556
		return -EEXIST;
C
Chris Mason 已提交
1557
	}
1558 1559
	if (ret < 0)
		goto out;
1560

1561 1562
	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1563
	leaf = btrfs_buffer_leaf(leaf_buf);
C
Chris Mason 已提交
1564

1565
	nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
1566
	data_end = leaf_data_end(root, leaf);
1567

C
Chris Mason 已提交
1568
	if (btrfs_leaf_free_space(root, leaf) <
1569
	    sizeof(struct btrfs_item) + data_size) {
1570
		BUG();
1571
	}
1572
	slot = path->slots[0];
1573
	BUG_ON(slot < 0);
1574 1575
	if (slot != nritems) {
		int i;
C
Chris Mason 已提交
1576
		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1577 1578 1579 1580 1581

		/*
		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
		 */
		/* first correct the data pointers */
C
Chris Mason 已提交
1582
		for (i = slot; i < nritems; i++) {
C
Chris Mason 已提交
1583
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1584 1585 1586
			btrfs_set_item_offset(leaf->items + i,
					      ioff - data_size);
		}
1587 1588

		/* shift the items */
C
Chris Mason 已提交
1589 1590 1591
		btrfs_memmove(root, leaf, leaf->items + slot + 1,
			      leaf->items + slot,
			      (nritems - slot) * sizeof(struct btrfs_item));
1592 1593

		/* shift the data */
C
Chris Mason 已提交
1594 1595 1596
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end - data_size, btrfs_leaf_data(leaf) +
			      data_end, old_data - data_end);
1597 1598
		data_end = old_data;
	}
1599
	/* setup the item for the new data */
C
Chris Mason 已提交
1600 1601
	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1602 1603
	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
	btrfs_set_item_size(leaf->items + slot, data_size);
1604
	btrfs_set_header_nritems(&leaf->header, nritems + 1);
C
Chris Mason 已提交
1605
	btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1606 1607

	ret = 0;
1608
	if (slot == 0)
1609
		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
C
Chris Mason 已提交
1610

C
Chris Mason 已提交
1611
	if (btrfs_leaf_free_space(root, leaf) < 0)
1612
		BUG();
1613
	check_leaf(root, path, 0);
1614
out:
1615 1616 1617 1618 1619 1620 1621
	return ret;
}

/*
 * Given a key and some data, insert an item into the tree.
 * This does all the path init required, making room in the tree if needed.
 */
1622 1623 1624
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *cpu_key, void *data, u32
		      data_size)
1625 1626
{
	int ret = 0;
C
Chris Mason 已提交
1627
	struct btrfs_path *path;
1628 1629
	u8 *ptr;

C
Chris Mason 已提交
1630 1631 1632 1633
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
1634
	if (!ret) {
C
Chris Mason 已提交
1635 1636 1637
		ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
				     path->slots[0], u8);
		btrfs_memcpy(root, path->nodes[0]->b_data,
C
Chris Mason 已提交
1638
			     ptr, data, data_size);
C
Chris Mason 已提交
1639
		btrfs_mark_buffer_dirty(path->nodes[0]);
1640
	}
C
Chris Mason 已提交
1641 1642
	btrfs_release_path(root, path);
	btrfs_free_path(path);
C
Chris Mason 已提交
1643
	return ret;
1644 1645
}

C
Chris Mason 已提交
1646
/*
C
Chris Mason 已提交
1647
 * delete the pointer from a given node.
C
Chris Mason 已提交
1648 1649 1650 1651 1652
 *
 * If the delete empties a node, the node is removed from the tree,
 * continuing all the way the root if required.  The root is converted into
 * a leaf if all the nodes are emptied.
 */
1653 1654
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot)
1655
{
C
Chris Mason 已提交
1656
	struct btrfs_node *node;
C
Chris Mason 已提交
1657
	struct buffer_head *parent = path->nodes[level];
1658
	u32 nritems;
C
Chris Mason 已提交
1659
	int ret = 0;
1660
	int wret;
1661

C
Chris Mason 已提交
1662
	node = btrfs_buffer_node(parent);
1663
	nritems = btrfs_header_nritems(&node->header);
1664
	if (slot != nritems -1) {
C
Chris Mason 已提交
1665 1666 1667 1668
		btrfs_memmove(root, node, node->ptrs + slot,
			      node->ptrs + slot + 1,
			      sizeof(struct btrfs_key_ptr) *
			      (nritems - slot - 1));
1669
	}
1670 1671 1672
	nritems--;
	btrfs_set_header_nritems(&node->header, nritems);
	if (nritems == 0 && parent == root->node) {
C
Chris Mason 已提交
1673 1674
		struct btrfs_header *header = btrfs_buffer_header(root->node);
		BUG_ON(btrfs_header_level(header) != 1);
1675
		/* just turn the root into a leaf and break */
C
Chris Mason 已提交
1676
		btrfs_set_header_level(header, 0);
1677
	} else if (slot == 0) {
1678
		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
C
Chris Mason 已提交
1679
				      level + 1);
C
Chris Mason 已提交
1680 1681
		if (wret)
			ret = wret;
1682
	}
C
Chris Mason 已提交
1683
	btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
1684
	return ret;
1685 1686
}

C
Chris Mason 已提交
1687 1688 1689 1690
/*
 * delete the item at the leaf level in path.  If that empties
 * the leaf, remove it from the tree
 */
1691 1692
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path)
1693 1694
{
	int slot;
C
Chris Mason 已提交
1695
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1696
	struct buffer_head *leaf_buf;
1697 1698
	int doff;
	int dsize;
C
Chris Mason 已提交
1699 1700
	int ret = 0;
	int wret;
1701
	u32 nritems;
1702

1703
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1704
	leaf = btrfs_buffer_leaf(leaf_buf);
1705
	slot = path->slots[0];
C
Chris Mason 已提交
1706 1707
	doff = btrfs_item_offset(leaf->items + slot);
	dsize = btrfs_item_size(leaf->items + slot);
1708
	nritems = btrfs_header_nritems(&leaf->header);
1709

1710
	if (slot != nritems - 1) {
1711
		int i;
C
Chris Mason 已提交
1712
		int data_end = leaf_data_end(root, leaf);
C
Chris Mason 已提交
1713 1714 1715 1716
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end + dsize,
			      btrfs_leaf_data(leaf) + data_end,
			      doff - data_end);
C
Chris Mason 已提交
1717
		for (i = slot + 1; i < nritems; i++) {
C
Chris Mason 已提交
1718
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1719 1720
			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
		}
C
Chris Mason 已提交
1721 1722 1723 1724
		btrfs_memmove(root, leaf, leaf->items + slot,
			      leaf->items + slot + 1,
			      sizeof(struct btrfs_item) *
			      (nritems - slot - 1));
1725
	}
1726 1727
	btrfs_set_header_nritems(&leaf->header, nritems - 1);
	nritems--;
C
Chris Mason 已提交
1728
	/* delete the leaf if we've emptied it */
1729
	if (nritems == 0) {
1730
		if (leaf_buf == root->node) {
1731
			btrfs_set_header_level(&leaf->header, 0);
1732
		} else {
1733
			clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1734
			wait_on_buffer(leaf_buf);
1735
			wret = del_ptr(trans, root, path, 1, path->slots[1]);
C
Chris Mason 已提交
1736 1737
			if (wret)
				ret = wret;
1738
			wret = btrfs_free_extent(trans, root,
1739
						 bh_blocknr(leaf_buf), 1, 1);
C
Chris Mason 已提交
1740 1741
			if (wret)
				ret = wret;
1742
		}
1743
	} else {
1744
		int used = leaf_space_used(leaf, 0, nritems);
C
Chris Mason 已提交
1745
		if (slot == 0) {
1746 1747
			wret = fixup_low_keys(trans, root, path,
					      &leaf->items[0].key, 1);
C
Chris Mason 已提交
1748 1749 1750 1751
			if (wret)
				ret = wret;
		}

C
Chris Mason 已提交
1752
		/* delete the leaf if it is mostly empty */
C
Chris Mason 已提交
1753
		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1754 1755 1756 1757
			/* push_leaf_left fixes the path.
			 * make sure the path still points to our leaf
			 * for possible call to del_ptr below
			 */
1758
			slot = path->slots[1];
C
Chris Mason 已提交
1759
			get_bh(leaf_buf);
1760
			wret = push_leaf_left(trans, root, path, 1);
C
Chris Mason 已提交
1761 1762
			if (wret < 0)
				ret = wret;
1763
			if (path->nodes[0] == leaf_buf &&
1764
			    btrfs_header_nritems(&leaf->header)) {
1765
				wret = push_leaf_right(trans, root, path, 1);
C
Chris Mason 已提交
1766 1767 1768
				if (wret < 0)
					ret = wret;
			}
1769
			if (btrfs_header_nritems(&leaf->header) == 0) {
1770
				u64 blocknr = bh_blocknr(leaf_buf);
1771
				clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1772
				wait_on_buffer(leaf_buf);
1773
				wret = del_ptr(trans, root, path, 1, slot);
C
Chris Mason 已提交
1774 1775
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1776
				btrfs_block_release(root, leaf_buf);
1777 1778
				wret = btrfs_free_extent(trans, root, blocknr,
							 1, 1);
C
Chris Mason 已提交
1779 1780
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1781
			} else {
C
Chris Mason 已提交
1782
				btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1783
				btrfs_block_release(root, leaf_buf);
1784
			}
1785
		} else {
C
Chris Mason 已提交
1786
			btrfs_mark_buffer_dirty(leaf_buf);
1787 1788
		}
	}
C
Chris Mason 已提交
1789
	return ret;
1790 1791
}

C
Chris Mason 已提交
1792 1793
/*
 * walk up the tree as far as required to find the next leaf.
C
Chris Mason 已提交
1794 1795
 * returns 0 if it found something or 1 if there are no greater leaves.
 * returns < 0 on io errors.
C
Chris Mason 已提交
1796
 */
C
Chris Mason 已提交
1797
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1798 1799 1800 1801
{
	int slot;
	int level = 1;
	u64 blocknr;
C
Chris Mason 已提交
1802 1803 1804
	struct buffer_head *c;
	struct btrfs_node *c_node;
	struct buffer_head *next = NULL;
1805

C
Chris Mason 已提交
1806
	while(level < BTRFS_MAX_LEVEL) {
1807
		if (!path->nodes[level])
C
Chris Mason 已提交
1808
			return 1;
1809 1810
		slot = path->slots[level] + 1;
		c = path->nodes[level];
C
Chris Mason 已提交
1811 1812
		c_node = btrfs_buffer_node(c);
		if (slot >= btrfs_header_nritems(&c_node->header)) {
1813 1814 1815
			level++;
			continue;
		}
C
Chris Mason 已提交
1816
		blocknr = btrfs_node_blockptr(c_node, slot);
C
Chris Mason 已提交
1817
		if (next)
C
Chris Mason 已提交
1818
			btrfs_block_release(root, next);
1819 1820 1821 1822 1823 1824 1825
		next = read_tree_block(root, blocknr);
		break;
	}
	path->slots[level] = slot;
	while(1) {
		level--;
		c = path->nodes[level];
C
Chris Mason 已提交
1826
		btrfs_block_release(root, c);
1827 1828 1829 1830
		path->nodes[level] = next;
		path->slots[level] = 0;
		if (!level)
			break;
1831
		next = read_tree_block(root,
C
Chris Mason 已提交
1832
		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1833 1834 1835
	}
	return 0;
}