ctree.c 44.5 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);
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 69
	memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
	btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr);
70
	btrfs_set_header_generation(&cow_node->header, trans->transid);
71
	btrfs_inc_ref(trans, root, buf);
C
Chris Mason 已提交
72 73
	if (buf == root->node) {
		root->node = cow;
C
Chris Mason 已提交
74
		get_bh(cow);
C
Chris Mason 已提交
75
		if (buf != root->commit_root) {
C
Chris Mason 已提交
76
			btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1);
C
Chris Mason 已提交
77
		}
C
Chris Mason 已提交
78
		btrfs_block_release(root, buf);
C
Chris Mason 已提交
79
	} else {
C
Chris Mason 已提交
80 81
		btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
					cow->b_blocknr);
C
Chris Mason 已提交
82
		btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
83
		btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1);
C
Chris Mason 已提交
84
	}
C
Chris Mason 已提交
85
	btrfs_block_release(root, buf);
C
Chris Mason 已提交
86
	mark_buffer_dirty(cow);
C
Chris Mason 已提交
87
	*cow_ret = cow;
C
Chris Mason 已提交
88 89 90
	return 0;
}

C
Chris Mason 已提交
91 92 93 94 95
/*
 * 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 已提交
96 97
static inline unsigned int leaf_data_end(struct btrfs_root *root,
					 struct btrfs_leaf *leaf)
98
{
99
	u32 nr = btrfs_header_nritems(&leaf->header);
100
	if (nr == 0)
C
Chris Mason 已提交
101
		return BTRFS_LEAF_DATA_SIZE(root);
C
Chris Mason 已提交
102
	return btrfs_item_offset(leaf->items + nr - 1);
103 104
}

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

	btrfs_disk_key_to_cpu(&k1, disk);

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

C
Chris Mason 已提交
129 130
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
131 132
{
	int i;
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
	u32 nritems = btrfs_header_nritems(&node->header);
C
Chris Mason 已提交
137 138

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

C
Chris Mason 已提交
159 160
static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
161 162
{
	int i;
C
Chris Mason 已提交
163
	struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
C
Chris Mason 已提交
164
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
165
	int parent_slot;
166
	u32 nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
167 168

	if (path->nodes[level + 1])
C
Chris Mason 已提交
169
		parent = btrfs_buffer_node(path->nodes[level + 1]);
C
Chris Mason 已提交
170
	parent_slot = path->slots[level + 1];
C
Chris Mason 已提交
171
	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
172 173 174 175 176

	if (nritems == 0)
		return 0;

	if (parent) {
C
Chris Mason 已提交
177
		struct btrfs_disk_key *parent_key;
C
Chris Mason 已提交
178
		parent_key = &parent->ptrs[parent_slot].key;
C
Chris Mason 已提交
179
		BUG_ON(memcmp(parent_key, &leaf->items[0].key,
C
Chris Mason 已提交
180
		       sizeof(struct btrfs_disk_key)));
181
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
182
		       btrfs_header_blocknr(&leaf->header));
C
Chris Mason 已提交
183
	}
184
	for (i = 0; nritems > 1 && i < nritems - 2; i++) {
C
Chris Mason 已提交
185 186
		struct btrfs_key cpukey;
		btrfs_disk_key_to_cpu(&cpukey, &leaf->items[i + 1].key);
C
Chris Mason 已提交
187
		BUG_ON(comp_keys(&leaf->items[i].key,
C
Chris Mason 已提交
188
		                 &cpukey) >= 0);
C
Chris Mason 已提交
189 190
		BUG_ON(btrfs_item_offset(leaf->items + i) !=
			btrfs_item_end(leaf->items + i + 1));
C
Chris Mason 已提交
191
		if (i == 0) {
C
Chris Mason 已提交
192 193
			BUG_ON(btrfs_item_offset(leaf->items + i) +
			       btrfs_item_size(leaf->items + i) !=
C
Chris Mason 已提交
194
			       BTRFS_LEAF_DATA_SIZE(root));
C
Chris Mason 已提交
195 196 197 198 199
		}
	}
	return 0;
}

C
Chris Mason 已提交
200 201
static int check_block(struct btrfs_root *root, struct btrfs_path *path,
			int level)
C
Chris Mason 已提交
202 203
{
	if (level == 0)
C
Chris Mason 已提交
204 205
		return check_leaf(root, path, level);
	return check_node(root, path, level);
C
Chris Mason 已提交
206 207
}

C
Chris Mason 已提交
208 209 210 211 212 213 214 215 216
/*
 * 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 已提交
217
static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
218 219 220 221 222 223
		       int max, int *slot)
{
	int low = 0;
	int high = max;
	int mid;
	int ret;
C
Chris Mason 已提交
224
	struct btrfs_disk_key *tmp;
225 226 227

	while(low < high) {
		mid = (low + high) / 2;
C
Chris Mason 已提交
228
		tmp = (struct btrfs_disk_key *)(p + mid * item_size);
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
		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 已提交
244 245 246 247
/*
 * simple bin_search frontend that does the right thing for
 * leaves vs nodes
 */
C
Chris Mason 已提交
248
static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
249
{
250
	if (btrfs_is_leaf(c)) {
C
Chris Mason 已提交
251
		struct btrfs_leaf *l = (struct btrfs_leaf *)c;
C
Chris Mason 已提交
252 253
		return generic_bin_search((void *)l->items,
					  sizeof(struct btrfs_item),
254 255
					  key, btrfs_header_nritems(&c->header),
					  slot);
256
	} else {
C
Chris Mason 已提交
257 258
		return generic_bin_search((void *)c->ptrs,
					  sizeof(struct btrfs_key_ptr),
259 260
					  key, btrfs_header_nritems(&c->header),
					  slot);
261 262 263 264
	}
	return -1;
}

C
Chris Mason 已提交
265 266
static struct buffer_head *read_node_slot(struct btrfs_root *root,
				   struct buffer_head *parent_buf,
267 268
				   int slot)
{
C
Chris Mason 已提交
269
	struct btrfs_node *node = btrfs_buffer_node(parent_buf);
270 271
	if (slot < 0)
		return NULL;
272
	if (slot >= btrfs_header_nritems(&node->header))
273
		return NULL;
274
	return read_tree_block(root, btrfs_node_blockptr(node, slot));
275 276
}

277 278
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
			 *root, struct btrfs_path *path, int level)
279
{
C
Chris Mason 已提交
280 281 282 283
	struct buffer_head *right_buf;
	struct buffer_head *mid_buf;
	struct buffer_head *left_buf;
	struct buffer_head *parent_buf = NULL;
C
Chris Mason 已提交
284 285 286 287
	struct btrfs_node *right = NULL;
	struct btrfs_node *mid;
	struct btrfs_node *left = NULL;
	struct btrfs_node *parent = NULL;
288 289 290 291
	int ret = 0;
	int wret;
	int pslot;
	int orig_slot = path->slots[level];
292
	u64 orig_ptr;
293 294 295 296 297

	if (level == 0)
		return 0;

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

C
Chris Mason 已提交
301
	if (level < BTRFS_MAX_LEVEL - 1)
302 303 304
		parent_buf = path->nodes[level + 1];
	pslot = path->slots[level + 1];

C
Chris Mason 已提交
305 306 307 308
	/*
	 * deal with the case where there is only one pointer in the root
	 * by promoting the node below to a root
	 */
309
	if (!parent_buf) {
C
Chris Mason 已提交
310 311
		struct buffer_head *child;
		u64 blocknr = mid_buf->b_blocknr;
312

313
		if (btrfs_header_nritems(&mid->header) != 1)
314 315 316 317 318 319 320
			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 已提交
321 322
		clean_tree_block(trans, root, mid_buf);
		wait_on_buffer(mid_buf);
323
		/* once for the path */
C
Chris Mason 已提交
324
		btrfs_block_release(root, mid_buf);
325
		/* once for the root ptr */
C
Chris Mason 已提交
326
		btrfs_block_release(root, mid_buf);
327
		return btrfs_free_extent(trans, root, blocknr, 1, 1);
328
	}
C
Chris Mason 已提交
329
	parent = btrfs_buffer_node(parent_buf);
330

C
Chris Mason 已提交
331 332
	if (btrfs_header_nritems(&mid->header) >
	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
333 334 335 336
		return 0;

	left_buf = read_node_slot(root, parent_buf, pslot - 1);
	right_buf = read_node_slot(root, parent_buf, pslot + 1);
337 338

	/* first, try to make some room in the middle buffer */
339
	if (left_buf) {
340 341
		btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1,
				&left_buf);
C
Chris Mason 已提交
342
		left = btrfs_buffer_node(left_buf);
343
		orig_slot += btrfs_header_nritems(&left->header);
344
		wret = push_node_left(trans, root, left_buf, mid_buf);
345 346
		if (wret < 0)
			ret = wret;
347
	}
348 349 350 351

	/*
	 * then try to empty the right most buffer into the middle
	 */
352
	if (right_buf) {
353 354
		btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1,
				&right_buf);
C
Chris Mason 已提交
355
		right = btrfs_buffer_node(right_buf);
356
		wret = push_node_left(trans, root, mid_buf, right_buf);
357 358
		if (wret < 0)
			ret = wret;
359
		if (btrfs_header_nritems(&right->header) == 0) {
C
Chris Mason 已提交
360
			u64 blocknr = right_buf->b_blocknr;
361
			clean_tree_block(trans, root, right_buf);
C
Chris Mason 已提交
362 363
			wait_on_buffer(right_buf);
			btrfs_block_release(root, right_buf);
364 365
			right_buf = NULL;
			right = NULL;
366 367
			wret = del_ptr(trans, root, path, level + 1, pslot +
				       1);
368 369
			if (wret)
				ret = wret;
370
			wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
371 372 373
			if (wret)
				ret = wret;
		} else {
C
Chris Mason 已提交
374 375 376 377 378
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot + 1].key,
				     &right->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
379 380
		}
	}
381
	if (btrfs_header_nritems(&mid->header) == 1) {
382 383 384 385 386 387 388 389 390 391
		/*
		 * 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);
392
		wret = balance_node_right(trans, root, mid_buf, left_buf);
393 394 395 396
		if (wret < 0)
			ret = wret;
		BUG_ON(wret == 1);
	}
397
	if (btrfs_header_nritems(&mid->header) == 0) {
398
		/* we've managed to empty the middle node, drop it */
C
Chris Mason 已提交
399
		u64 blocknr = mid_buf->b_blocknr;
400
		clean_tree_block(trans, root, mid_buf);
C
Chris Mason 已提交
401 402
		wait_on_buffer(mid_buf);
		btrfs_block_release(root, mid_buf);
403 404
		mid_buf = NULL;
		mid = NULL;
405
		wret = del_ptr(trans, root, path, level + 1, pslot);
406 407
		if (wret)
			ret = wret;
408
		wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
409 410
		if (wret)
			ret = wret;
411 412
	} else {
		/* update the parent key to reflect our changes */
C
Chris Mason 已提交
413 414 415 416
		btrfs_memcpy(root, parent,
			     &parent->ptrs[pslot].key, &mid->ptrs[0].key,
			     sizeof(struct btrfs_disk_key));
		btrfs_mark_buffer_dirty(parent_buf);
417
	}
418

419
	/* update the path */
420
	if (left_buf) {
421
		if (btrfs_header_nritems(&left->header) > orig_slot) {
C
Chris Mason 已提交
422
			get_bh(left_buf);
423 424 425 426
			path->nodes[level] = left_buf;
			path->slots[level + 1] -= 1;
			path->slots[level] = orig_slot;
			if (mid_buf)
C
Chris Mason 已提交
427
				btrfs_block_release(root, mid_buf);
428
		} else {
429
			orig_slot -= btrfs_header_nritems(&left->header);
430 431 432
			path->slots[level] = orig_slot;
		}
	}
433
	/* double check we haven't messed things up */
C
Chris Mason 已提交
434
	check_block(root, path, level);
C
Chris Mason 已提交
435 436 437
	if (orig_ptr !=
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
				path->slots[level]))
438
		BUG();
439 440

	if (right_buf)
C
Chris Mason 已提交
441
		btrfs_block_release(root, right_buf);
442
	if (left_buf)
C
Chris Mason 已提交
443
		btrfs_block_release(root, left_buf);
444 445 446
	return ret;
}

C
Chris Mason 已提交
447 448 449 450 451 452
/*
 * 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 已提交
453 454
 * be inserted, and 1 is returned.  If there are other errors during the
 * search a negative error number is returned.
C
Chris Mason 已提交
455 456 457 458
 *
 * 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 已提交
459
 */
460 461 462
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)
463
{
C
Chris Mason 已提交
464 465
	struct buffer_head *b;
	struct buffer_head *cow_buf;
C
Chris Mason 已提交
466
	struct btrfs_node *c;
467 468 469
	int slot;
	int ret;
	int level;
C
Chris Mason 已提交
470

C
Chris Mason 已提交
471 472
	WARN_ON(p->nodes[0] != NULL);
	WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
473 474
again:
	b = root->node;
C
Chris Mason 已提交
475
	get_bh(b);
476
	while (b) {
C
Chris Mason 已提交
477 478
		c = btrfs_buffer_node(b);
		level = btrfs_header_level(&c->header);
C
Chris Mason 已提交
479 480
		if (cow) {
			int wret;
C
Chris Mason 已提交
481 482 483
			wret = btrfs_cow_block(trans, root, b,
					       p->nodes[level + 1],
					       p->slots[level + 1],
484
					       &cow_buf);
C
Chris Mason 已提交
485
			b = cow_buf;
C
Chris Mason 已提交
486
			c = btrfs_buffer_node(b);
C
Chris Mason 已提交
487 488
		}
		BUG_ON(!cow && ins_len);
C
Chris Mason 已提交
489 490 491
		if (level != btrfs_header_level(&c->header))
			WARN_ON(1);
		level = btrfs_header_level(&c->header);
492
		p->nodes[level] = b;
C
Chris Mason 已提交
493
		ret = check_block(root, p, level);
C
Chris Mason 已提交
494 495
		if (ret)
			return -1;
496
		ret = bin_search(c, key, &slot);
497
		if (!btrfs_is_leaf(c)) {
498 499 500
			if (ret && slot > 0)
				slot -= 1;
			p->slots[level] = slot;
501 502
			if (ins_len > 0 && btrfs_header_nritems(&c->header) >=
			    BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
503
				int sret = split_node(trans, root, p, level);
C
Chris Mason 已提交
504 505 506 507
				BUG_ON(sret > 0);
				if (sret)
					return sret;
				b = p->nodes[level];
C
Chris Mason 已提交
508
				c = btrfs_buffer_node(b);
C
Chris Mason 已提交
509
				slot = p->slots[level];
510
			} else if (ins_len < 0) {
511 512
				int sret = balance_level(trans, root, p,
							 level);
513 514 515 516 517
				if (sret)
					return sret;
				b = p->nodes[level];
				if (!b)
					goto again;
C
Chris Mason 已提交
518
				c = btrfs_buffer_node(b);
519
				slot = p->slots[level];
520
				BUG_ON(btrfs_header_nritems(&c->header) == 1);
C
Chris Mason 已提交
521
			}
522
			b = read_tree_block(root, btrfs_node_blockptr(c, slot));
523
		} else {
C
Chris Mason 已提交
524
			struct btrfs_leaf *l = (struct btrfs_leaf *)c;
525
			p->slots[level] = slot;
C
Chris Mason 已提交
526
			if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
C
Chris Mason 已提交
527
			    sizeof(struct btrfs_item) + ins_len) {
528 529
				int sret = split_leaf(trans, root, key,
						      p, ins_len);
C
Chris Mason 已提交
530 531 532 533
				BUG_ON(sret > 0);
				if (sret)
					return sret;
			}
534 535 536
			return ret;
		}
	}
C
Chris Mason 已提交
537
	return 1;
538 539
}

C
Chris Mason 已提交
540 541 542 543 544 545
/*
 * 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 已提交
546 547 548
 *
 * 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 已提交
549
 */
550 551 552
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)
553 554
{
	int i;
C
Chris Mason 已提交
555
	int ret = 0;
C
Chris Mason 已提交
556 557
	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
		struct btrfs_node *t;
558
		int tslot = path->slots[i];
559
		if (!path->nodes[i])
560
			break;
C
Chris Mason 已提交
561
		t = btrfs_buffer_node(path->nodes[i]);
C
Chris Mason 已提交
562 563
		btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
		btrfs_mark_buffer_dirty(path->nodes[i]);
564 565 566
		if (tslot != 0)
			break;
	}
C
Chris Mason 已提交
567
	return ret;
568 569
}

C
Chris Mason 已提交
570 571
/*
 * try to push data from one node into the next node left in the
572
 * tree.
C
Chris Mason 已提交
573 574 575
 *
 * 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 已提交
576
 */
577
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
578 579
			  *root, struct buffer_head *dst_buf, struct
			  buffer_head *src_buf)
580
{
C
Chris Mason 已提交
581 582
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
583
	int push_items = 0;
584 585
	int src_nritems;
	int dst_nritems;
C
Chris Mason 已提交
586
	int ret = 0;
587

588 589
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
590
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
591
	if (push_items <= 0) {
592
		return 1;
593
	}
594

595
	if (src_nritems < push_items)
596 597
		push_items = src_nritems;

C
Chris Mason 已提交
598 599
	btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
		     push_items * sizeof(struct btrfs_key_ptr));
600
	if (push_items < src_nritems) {
C
Chris Mason 已提交
601
		btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
C
Chris Mason 已提交
602
			(src_nritems - push_items) *
C
Chris Mason 已提交
603
			sizeof(struct btrfs_key_ptr));
604
	}
605 606
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
C
Chris Mason 已提交
607 608
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
609 610 611 612 613 614 615 616 617 618 619 620
	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
 */
621
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
622 623
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf)
624
{
C
Chris Mason 已提交
625 626
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
627 628 629 630 631 632
	int push_items = 0;
	int max_push;
	int src_nritems;
	int dst_nritems;
	int ret = 0;

633 634
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
635
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
636 637 638 639 640 641 642 643 644 645 646
	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 已提交
647 648 649 650 651 652
	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));
653

654 655
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
656

C
Chris Mason 已提交
657 658
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
C
Chris Mason 已提交
659
	return ret;
660 661
}

C
Chris Mason 已提交
662 663 664 665
/*
 * 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 已提交
666 667
 *
 * returns zero on success or < 0 on failure.
C
Chris Mason 已提交
668
 */
669 670
static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int level)
C
Chris Mason 已提交
671
{
C
Chris Mason 已提交
672
	struct buffer_head *t;
C
Chris Mason 已提交
673 674
	struct btrfs_node *lower;
	struct btrfs_node *c;
C
Chris Mason 已提交
675
	struct btrfs_disk_key *lower_key;
C
Chris Mason 已提交
676 677 678 679

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

680
	t = btrfs_alloc_free_block(trans, root);
C
Chris Mason 已提交
681
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
682
	memset(c, 0, root->blocksize);
683 684
	btrfs_set_header_nritems(&c->header, 1);
	btrfs_set_header_level(&c->header, level);
C
Chris Mason 已提交
685
	btrfs_set_header_blocknr(&c->header, t->b_blocknr);
686
	btrfs_set_header_generation(&c->header, trans->transid);
687
	btrfs_set_header_parentid(&c->header,
C
Chris Mason 已提交
688 689
	      btrfs_header_parentid(btrfs_buffer_header(root->node)));
	lower = btrfs_buffer_node(path->nodes[level-1]);
690
	if (btrfs_is_leaf(lower))
C
Chris Mason 已提交
691
		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
C
Chris Mason 已提交
692
	else
C
Chris Mason 已提交
693
		lower_key = &lower->ptrs[0].key;
C
Chris Mason 已提交
694 695
	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
696
	btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr);
697

C
Chris Mason 已提交
698
	btrfs_mark_buffer_dirty(t);
699

C
Chris Mason 已提交
700
	/* the super has an extra ref to root->node */
C
Chris Mason 已提交
701
	btrfs_block_release(root, root->node);
C
Chris Mason 已提交
702
	root->node = t;
C
Chris Mason 已提交
703
	get_bh(t);
C
Chris Mason 已提交
704 705 706 707 708
	path->nodes[level] = t;
	path->slots[level] = 0;
	return 0;
}

C
Chris Mason 已提交
709 710 711
/*
 * worker function to insert a single pointer in a node.
 * the node should have enough room for the pointer already
C
Chris Mason 已提交
712
 *
C
Chris Mason 已提交
713 714
 * slot and level indicate where you want the key to go, and
 * blocknr is the block the key points to.
C
Chris Mason 已提交
715 716
 *
 * returns zero on success and < 0 on any error
C
Chris Mason 已提交
717
 */
718 719 720
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 已提交
721
{
C
Chris Mason 已提交
722
	struct btrfs_node *lower;
C
Chris Mason 已提交
723
	int nritems;
C
Chris Mason 已提交
724 725

	BUG_ON(!path->nodes[level]);
C
Chris Mason 已提交
726
	lower = btrfs_buffer_node(path->nodes[level]);
727
	nritems = btrfs_header_nritems(&lower->header);
C
Chris Mason 已提交
728 729
	if (slot > nritems)
		BUG();
C
Chris Mason 已提交
730
	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
C
Chris Mason 已提交
731 732
		BUG();
	if (slot != nritems) {
C
Chris Mason 已提交
733 734 735
		btrfs_memmove(root, lower, lower->ptrs + slot + 1,
			      lower->ptrs + slot,
			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
C
Chris Mason 已提交
736
	}
C
Chris Mason 已提交
737 738
	btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
		     key, sizeof(struct btrfs_disk_key));
739
	btrfs_set_node_blockptr(lower, slot, blocknr);
740
	btrfs_set_header_nritems(&lower->header, nritems + 1);
C
Chris Mason 已提交
741
	btrfs_mark_buffer_dirty(path->nodes[level]);
C
Chris Mason 已提交
742 743 744
	return 0;
}

C
Chris Mason 已提交
745 746 747 748 749 750
/*
 * 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 已提交
751 752
 *
 * returns 0 on success and < 0 on failure
C
Chris Mason 已提交
753
 */
754 755
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, int level)
756
{
C
Chris Mason 已提交
757
	struct buffer_head *t;
C
Chris Mason 已提交
758
	struct btrfs_node *c;
C
Chris Mason 已提交
759
	struct buffer_head *split_buffer;
C
Chris Mason 已提交
760
	struct btrfs_node *split;
761
	int mid;
C
Chris Mason 已提交
762
	int ret;
C
Chris Mason 已提交
763
	int wret;
764
	u32 c_nritems;
765

C
Chris Mason 已提交
766
	t = path->nodes[level];
C
Chris Mason 已提交
767
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
768 769
	if (t == root->node) {
		/* trying to split the root, lets make a new one */
770
		ret = insert_new_root(trans, root, path, level + 1);
C
Chris Mason 已提交
771 772
		if (ret)
			return ret;
773
	}
774
	c_nritems = btrfs_header_nritems(&c->header);
775
	split_buffer = btrfs_alloc_free_block(trans, root);
C
Chris Mason 已提交
776
	split = btrfs_buffer_node(split_buffer);
777
	btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
778
	btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
C
Chris Mason 已提交
779
	btrfs_set_header_blocknr(&split->header, split_buffer->b_blocknr);
780
	btrfs_set_header_generation(&split->header, trans->transid);
781
	btrfs_set_header_parentid(&split->header,
C
Chris Mason 已提交
782
	      btrfs_header_parentid(btrfs_buffer_header(root->node)));
783
	mid = (c_nritems + 1) / 2;
C
Chris Mason 已提交
784 785
	btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
		     (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
786 787
	btrfs_set_header_nritems(&split->header, c_nritems - mid);
	btrfs_set_header_nritems(&c->header, mid);
C
Chris Mason 已提交
788 789
	ret = 0;

C
Chris Mason 已提交
790 791
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(split_buffer);
792
	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
C
Chris Mason 已提交
793
			  split_buffer->b_blocknr, path->slots[level + 1] + 1,
C
Chris Mason 已提交
794
			  level + 1);
C
Chris Mason 已提交
795 796 797
	if (wret)
		ret = wret;

C
Chris Mason 已提交
798
	if (path->slots[level] >= mid) {
C
Chris Mason 已提交
799
		path->slots[level] -= mid;
C
Chris Mason 已提交
800
		btrfs_block_release(root, t);
C
Chris Mason 已提交
801 802 803
		path->nodes[level] = split_buffer;
		path->slots[level + 1] += 1;
	} else {
C
Chris Mason 已提交
804
		btrfs_block_release(root, split_buffer);
805
	}
C
Chris Mason 已提交
806
	return ret;
807 808
}

C
Chris Mason 已提交
809 810 811 812 813
/*
 * 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 已提交
814
static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
815 816
{
	int data_len;
817 818
	int nritems = btrfs_header_nritems(&l->header);
	int end = min(nritems, start + nr) - 1;
819 820 821

	if (!nr)
		return 0;
C
Chris Mason 已提交
822 823 824
	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;
825
	WARN_ON(data_len < 0);
826 827 828
	return data_len;
}

829 830 831 832 833 834 835 836 837 838 839
/*
 * 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 已提交
840 841 842
/*
 * 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 已提交
843 844 845
 *
 * 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 已提交
846
 */
847 848
static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int data_size)
C
Chris Mason 已提交
849
{
C
Chris Mason 已提交
850 851
	struct buffer_head *left_buf = path->nodes[0];
	struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
C
Chris Mason 已提交
852
	struct btrfs_leaf *right;
C
Chris Mason 已提交
853 854 855
	struct buffer_head *right_buf;
	struct buffer_head *upper;
	struct btrfs_node *upper_node;
C
Chris Mason 已提交
856 857 858 859 860
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
861
	struct btrfs_item *item;
862 863
	u32 left_nritems;
	u32 right_nritems;
C
Chris Mason 已提交
864 865 866 867 868 869

	slot = path->slots[1];
	if (!path->nodes[1]) {
		return 1;
	}
	upper = path->nodes[1];
C
Chris Mason 已提交
870 871
	upper_node = btrfs_buffer_node(upper);
	if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
C
Chris Mason 已提交
872 873
		return 1;
	}
C
Chris Mason 已提交
874 875 876
	right_buf = read_tree_block(root,
		    btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
877
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
878
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
879
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
880 881
		return 1;
	}
C
Chris Mason 已提交
882
	/* cow and double check */
883
	btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf);
C
Chris Mason 已提交
884
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
885
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
886
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
887
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
888 889 890
		return 1;
	}

891 892
	left_nritems = btrfs_header_nritems(&left->header);
	for (i = left_nritems - 1; i >= 0; i--) {
C
Chris Mason 已提交
893 894 895
		item = left->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
896 897
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
C
Chris Mason 已提交
898 899
			break;
		push_items++;
C
Chris Mason 已提交
900
		push_space += btrfs_item_size(item) + sizeof(*item);
C
Chris Mason 已提交
901 902
	}
	if (push_items == 0) {
C
Chris Mason 已提交
903
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
904 905
		return 1;
	}
906
	right_nritems = btrfs_header_nritems(&right->header);
C
Chris Mason 已提交
907
	/* push left to right */
C
Chris Mason 已提交
908
	push_space = btrfs_item_end(left->items + left_nritems - push_items);
C
Chris Mason 已提交
909
	push_space -= leaf_data_end(root, left);
C
Chris Mason 已提交
910
	/* make room in the right data area */
C
Chris Mason 已提交
911 912 913 914 915
	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 已提交
916
	/* copy from the left data area */
C
Chris Mason 已提交
917 918 919 920 921
	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 已提交
922
		right_nritems * sizeof(struct btrfs_item));
C
Chris Mason 已提交
923
	/* copy the items from left to right */
C
Chris Mason 已提交
924 925 926
	btrfs_memcpy(root, right, right->items, left->items +
		     left_nritems - push_items,
		     push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
927 928

	/* update the item pointers */
929 930
	right_nritems += push_items;
	btrfs_set_header_nritems(&right->header, right_nritems);
C
Chris Mason 已提交
931
	push_space = BTRFS_LEAF_DATA_SIZE(root);
932
	for (i = 0; i < right_nritems; i++) {
C
Chris Mason 已提交
933 934 935
		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 已提交
936
	}
937 938
	left_nritems -= push_items;
	btrfs_set_header_nritems(&left->header, left_nritems);
C
Chris Mason 已提交
939

C
Chris Mason 已提交
940 941 942
	btrfs_mark_buffer_dirty(left_buf);
	btrfs_mark_buffer_dirty(right_buf);
	btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key,
C
Chris Mason 已提交
943
		&right->items[0].key, sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
944
	btrfs_mark_buffer_dirty(upper);
C
Chris Mason 已提交
945

C
Chris Mason 已提交
946
	/* then fixup the leaf pointer in the path */
947 948
	if (path->slots[0] >= left_nritems) {
		path->slots[0] -= left_nritems;
C
Chris Mason 已提交
949
		btrfs_block_release(root, path->nodes[0]);
C
Chris Mason 已提交
950 951 952
		path->nodes[0] = right_buf;
		path->slots[1] += 1;
	} else {
C
Chris Mason 已提交
953
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
954 955 956
	}
	return 0;
}
C
Chris Mason 已提交
957 958 959 960
/*
 * 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
 */
961 962
static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int data_size)
963
{
C
Chris Mason 已提交
964 965 966
	struct buffer_head *right_buf = path->nodes[0];
	struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
	struct buffer_head *t;
C
Chris Mason 已提交
967
	struct btrfs_leaf *left;
968 969 970 971 972
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
973
	struct btrfs_item *item;
974
	u32 old_left_nritems;
C
Chris Mason 已提交
975 976
	int ret = 0;
	int wret;
977 978 979 980 981 982 983 984

	slot = path->slots[1];
	if (slot == 0) {
		return 1;
	}
	if (!path->nodes[1]) {
		return 1;
	}
C
Chris Mason 已提交
985 986 987
	t = read_tree_block(root,
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
988
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
989
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
990
		btrfs_block_release(root, t);
991 992
		return 1;
	}
C
Chris Mason 已提交
993 994

	/* cow and double check */
995
	btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
C
Chris Mason 已提交
996
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
997
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
998
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
999
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1000 1001 1002
		return 1;
	}

1003
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
1004 1005 1006
		item = right->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1007 1008
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
1009 1010
			break;
		push_items++;
C
Chris Mason 已提交
1011
		push_space += btrfs_item_size(item) + sizeof(*item);
1012 1013
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1014
		btrfs_block_release(root, t);
1015 1016 1017
		return 1;
	}
	/* push data from right to left */
C
Chris Mason 已提交
1018 1019 1020
	btrfs_memcpy(root, left, left->items +
		     btrfs_header_nritems(&left->header),
		     right->items, push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1021
	push_space = BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1022
		     btrfs_item_offset(right->items + push_items -1);
C
Chris Mason 已提交
1023 1024 1025 1026 1027
	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);
1028
	old_left_nritems = btrfs_header_nritems(&left->header);
1029 1030
	BUG_ON(old_left_nritems < 0);

C
Chris Mason 已提交
1031
	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
C
Chris Mason 已提交
1032 1033 1034
		u32 ioff = btrfs_item_offset(left->items + i);
		btrfs_set_item_offset(left->items + i, ioff -
				     (BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1035 1036
				      btrfs_item_offset(left->items +
						        old_left_nritems - 1)));
1037
	}
1038
	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1039 1040

	/* fixup right node */
C
Chris Mason 已提交
1041
	push_space = btrfs_item_offset(right->items + push_items - 1) -
C
Chris Mason 已提交
1042
		     leaf_data_end(root, right);
C
Chris Mason 已提交
1043 1044 1045 1046 1047
	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,
1048
		(btrfs_header_nritems(&right->header) - push_items) *
C
Chris Mason 已提交
1049
		sizeof(struct btrfs_item));
1050 1051 1052
	btrfs_set_header_nritems(&right->header,
				 btrfs_header_nritems(&right->header) -
				 push_items);
C
Chris Mason 已提交
1053
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1054

1055
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1056 1057 1058
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
1059
	}
1060

C
Chris Mason 已提交
1061 1062
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);
1063

1064
	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
C
Chris Mason 已提交
1065 1066
	if (wret)
		ret = wret;
1067 1068 1069 1070

	/* then fixup the leaf pointer in the path */
	if (path->slots[0] < push_items) {
		path->slots[0] += old_left_nritems;
C
Chris Mason 已提交
1071
		btrfs_block_release(root, path->nodes[0]);
1072
		path->nodes[0] = t;
1073 1074
		path->slots[1] -= 1;
	} else {
C
Chris Mason 已提交
1075
		btrfs_block_release(root, t);
1076 1077
		path->slots[0] -= push_items;
	}
1078
	BUG_ON(path->slots[0] < 0);
C
Chris Mason 已提交
1079
	return ret;
1080 1081
}

C
Chris Mason 已提交
1082 1083 1084
/*
 * 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 已提交
1085 1086
 *
 * returns 0 if all went well and < 0 on failure.
C
Chris Mason 已提交
1087
 */
1088
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1089 1090
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size)
1091
{
C
Chris Mason 已提交
1092
	struct buffer_head *l_buf;
C
Chris Mason 已提交
1093
	struct btrfs_leaf *l;
1094
	u32 nritems;
1095 1096
	int mid;
	int slot;
C
Chris Mason 已提交
1097
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1098
	struct buffer_head *right_buffer;
C
Chris Mason 已提交
1099
	int space_needed = data_size + sizeof(struct btrfs_item);
1100 1101 1102
	int data_copy_size;
	int rt_data_off;
	int i;
1103
	int ret = 0;
C
Chris Mason 已提交
1104
	int wret;
1105 1106
	int double_split = 0;
	struct btrfs_disk_key disk_key;
C
Chris Mason 已提交
1107

C
Chris Mason 已提交
1108
	/* first try to make some room by pushing left and right */
1109
	wret = push_leaf_left(trans, root, path, data_size);
C
Chris Mason 已提交
1110 1111 1112
	if (wret < 0)
		return wret;
	if (wret) {
1113
		wret = push_leaf_right(trans, root, path, data_size);
C
Chris Mason 已提交
1114 1115 1116
		if (wret < 0)
			return wret;
	}
C
Chris Mason 已提交
1117
	l_buf = path->nodes[0];
C
Chris Mason 已提交
1118
	l = btrfs_buffer_leaf(l_buf);
C
Chris Mason 已提交
1119 1120

	/* did the pushes work? */
C
Chris Mason 已提交
1121 1122
	if (btrfs_leaf_free_space(root, l) >=
	    sizeof(struct btrfs_item) + data_size)
C
Chris Mason 已提交
1123 1124
		return 0;

C
Chris Mason 已提交
1125
	if (!path->nodes[1]) {
1126
		ret = insert_new_root(trans, root, path, 1);
C
Chris Mason 已提交
1127 1128 1129
		if (ret)
			return ret;
	}
1130
	slot = path->slots[0];
1131
	nritems = btrfs_header_nritems(&l->header);
1132
	mid = (nritems + 1)/ 2;
1133
	right_buffer = btrfs_alloc_free_block(trans, root);
1134
	BUG_ON(!right_buffer);
C
Chris Mason 已提交
1135
	right = btrfs_buffer_leaf(right_buffer);
C
Chris Mason 已提交
1136
	memset(&right->header, 0, sizeof(right->header));
C
Chris Mason 已提交
1137
	btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr);
1138
	btrfs_set_header_generation(&right->header, trans->transid);
1139 1140
	btrfs_set_header_level(&right->header, 0);
	btrfs_set_header_parentid(&right->header,
C
Chris Mason 已提交
1141
	      btrfs_header_parentid(btrfs_buffer_header(root->node)));
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
	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,
						  right_buffer->b_blocknr,
						  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,
						  right_buffer->b_blocknr,
						  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;
		}
	}
	btrfs_set_header_nritems(&right->header, nritems - mid);
C
Chris Mason 已提交
1187 1188
	data_copy_size = btrfs_item_end(l->items + mid) -
			 leaf_data_end(root, l);
C
Chris Mason 已提交
1189 1190 1191 1192 1193 1194
	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 已提交
1195 1196
	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
		      btrfs_item_end(l->items + mid);
C
Chris Mason 已提交
1197

C
Chris Mason 已提交
1198
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1199
		u32 ioff = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1200 1201
		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
	}
C
Chris Mason 已提交
1202

1203
	btrfs_set_header_nritems(&l->header, mid);
C
Chris Mason 已提交
1204
	ret = 0;
1205
	wret = insert_ptr(trans, root, path, &right->items[0].key,
C
Chris Mason 已提交
1206
			  right_buffer->b_blocknr, path->slots[1] + 1, 1);
C
Chris Mason 已提交
1207 1208
	if (wret)
		ret = wret;
C
Chris Mason 已提交
1209 1210
	btrfs_mark_buffer_dirty(right_buffer);
	btrfs_mark_buffer_dirty(l_buf);
1211
	BUG_ON(path->slots[0] != slot);
1212
	if (mid <= slot) {
C
Chris Mason 已提交
1213
		btrfs_block_release(root, path->nodes[0]);
1214
		path->nodes[0] = right_buffer;
1215 1216
		path->slots[0] -= mid;
		path->slots[1] += 1;
1217
	} else
C
Chris Mason 已提交
1218
		btrfs_block_release(root, right_buffer);
1219
	BUG_ON(path->slots[0] < 0);
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244

	if (!double_split)
		return ret;
	right_buffer = btrfs_alloc_free_block(trans, root);
	BUG_ON(!right_buffer);
	right = btrfs_buffer_leaf(right_buffer);
	memset(&right->header, 0, sizeof(right->header));
	btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr);
	btrfs_set_header_generation(&right->header, trans->transid);
	btrfs_set_header_level(&right->header, 0);
	btrfs_set_header_parentid(&right->header,
	      btrfs_header_parentid(btrfs_buffer_header(root->node)));
	btrfs_cpu_key_to_disk(&disk_key, ins_key);
	btrfs_set_header_nritems(&right->header, 0);
	wret = insert_ptr(trans, root, path,
			  &disk_key,
			  right_buffer->b_blocknr,
			  path->slots[1], 1);
	if (wret)
		ret = wret;
	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);
1245 1246 1247
	return ret;
}

C
Chris Mason 已提交
1248 1249 1250 1251
/*
 * 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.
 */
1252 1253 1254
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)
1255
{
C
Chris Mason 已提交
1256
	int ret = 0;
1257
	int slot;
1258
	int slot_orig;
C
Chris Mason 已提交
1259
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1260
	struct buffer_head *leaf_buf;
1261
	u32 nritems;
1262
	unsigned int data_end;
C
Chris Mason 已提交
1263 1264 1265
	struct btrfs_disk_key disk_key;

	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1266

C
Chris Mason 已提交
1267
	/* create a root if there isn't one */
C
Chris Mason 已提交
1268
	if (!root->node)
C
Chris Mason 已提交
1269
		BUG();
1270
	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1271
	if (ret == 0) {
1272
		return -EEXIST;
C
Chris Mason 已提交
1273
	}
1274 1275
	if (ret < 0)
		goto out;
1276

1277 1278
	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1279
	leaf = btrfs_buffer_leaf(leaf_buf);
C
Chris Mason 已提交
1280

1281
	nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
1282
	data_end = leaf_data_end(root, leaf);
1283

C
Chris Mason 已提交
1284
	if (btrfs_leaf_free_space(root, leaf) <
1285
	    sizeof(struct btrfs_item) + data_size) {
1286
		BUG();
1287
	}
1288
	slot = path->slots[0];
1289
	BUG_ON(slot < 0);
1290 1291
	if (slot != nritems) {
		int i;
C
Chris Mason 已提交
1292
		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1293 1294 1295 1296 1297

		/*
		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
		 */
		/* first correct the data pointers */
C
Chris Mason 已提交
1298
		for (i = slot; i < nritems; i++) {
C
Chris Mason 已提交
1299
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1300 1301 1302
			btrfs_set_item_offset(leaf->items + i,
					      ioff - data_size);
		}
1303 1304

		/* shift the items */
C
Chris Mason 已提交
1305 1306 1307
		btrfs_memmove(root, leaf, leaf->items + slot + 1,
			      leaf->items + slot,
			      (nritems - slot) * sizeof(struct btrfs_item));
1308 1309

		/* shift the data */
C
Chris Mason 已提交
1310 1311 1312
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end - data_size, btrfs_leaf_data(leaf) +
			      data_end, old_data - data_end);
1313 1314
		data_end = old_data;
	}
1315
	/* setup the item for the new data */
C
Chris Mason 已提交
1316 1317
	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1318 1319
	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
	btrfs_set_item_size(leaf->items + slot, data_size);
1320
	btrfs_set_header_nritems(&leaf->header, nritems + 1);
C
Chris Mason 已提交
1321
	btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1322 1323

	ret = 0;
1324
	if (slot == 0)
1325
		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
C
Chris Mason 已提交
1326

C
Chris Mason 已提交
1327
	if (btrfs_leaf_free_space(root, leaf) < 0)
1328
		BUG();
1329
	check_leaf(root, path, 0);
1330
out:
1331 1332 1333 1334 1335 1336 1337
	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.
 */
1338 1339 1340
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *cpu_key, void *data, u32
		      data_size)
1341 1342
{
	int ret = 0;
C
Chris Mason 已提交
1343
	struct btrfs_path *path;
1344 1345
	u8 *ptr;

C
Chris Mason 已提交
1346 1347 1348 1349
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
1350
	if (!ret) {
C
Chris Mason 已提交
1351 1352 1353
		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 已提交
1354
			     ptr, data, data_size);
C
Chris Mason 已提交
1355
		btrfs_mark_buffer_dirty(path->nodes[0]);
1356
	}
C
Chris Mason 已提交
1357 1358
	btrfs_release_path(root, path);
	btrfs_free_path(path);
C
Chris Mason 已提交
1359
	return ret;
1360 1361
}

C
Chris Mason 已提交
1362
/*
C
Chris Mason 已提交
1363
 * delete the pointer from a given node.
C
Chris Mason 已提交
1364 1365 1366 1367 1368
 *
 * 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.
 */
1369 1370
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot)
1371
{
C
Chris Mason 已提交
1372
	struct btrfs_node *node;
C
Chris Mason 已提交
1373
	struct buffer_head *parent = path->nodes[level];
1374
	u32 nritems;
C
Chris Mason 已提交
1375
	int ret = 0;
1376
	int wret;
1377

C
Chris Mason 已提交
1378
	node = btrfs_buffer_node(parent);
1379
	nritems = btrfs_header_nritems(&node->header);
1380
	if (slot != nritems -1) {
C
Chris Mason 已提交
1381 1382 1383 1384
		btrfs_memmove(root, node, node->ptrs + slot,
			      node->ptrs + slot + 1,
			      sizeof(struct btrfs_key_ptr) *
			      (nritems - slot - 1));
1385
	}
1386 1387 1388
	nritems--;
	btrfs_set_header_nritems(&node->header, nritems);
	if (nritems == 0 && parent == root->node) {
C
Chris Mason 已提交
1389 1390
		struct btrfs_header *header = btrfs_buffer_header(root->node);
		BUG_ON(btrfs_header_level(header) != 1);
1391
		/* just turn the root into a leaf and break */
C
Chris Mason 已提交
1392
		btrfs_set_header_level(header, 0);
1393
	} else if (slot == 0) {
1394
		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
C
Chris Mason 已提交
1395
				      level + 1);
C
Chris Mason 已提交
1396 1397
		if (wret)
			ret = wret;
1398
	}
C
Chris Mason 已提交
1399
	btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
1400
	return ret;
1401 1402
}

C
Chris Mason 已提交
1403 1404 1405 1406
/*
 * delete the item at the leaf level in path.  If that empties
 * the leaf, remove it from the tree
 */
1407 1408
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path)
1409 1410
{
	int slot;
C
Chris Mason 已提交
1411
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1412
	struct buffer_head *leaf_buf;
1413 1414
	int doff;
	int dsize;
C
Chris Mason 已提交
1415 1416
	int ret = 0;
	int wret;
1417
	u32 nritems;
1418

1419
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1420
	leaf = btrfs_buffer_leaf(leaf_buf);
1421
	slot = path->slots[0];
C
Chris Mason 已提交
1422 1423
	doff = btrfs_item_offset(leaf->items + slot);
	dsize = btrfs_item_size(leaf->items + slot);
1424
	nritems = btrfs_header_nritems(&leaf->header);
1425

1426
	if (slot != nritems - 1) {
1427
		int i;
C
Chris Mason 已提交
1428
		int data_end = leaf_data_end(root, leaf);
C
Chris Mason 已提交
1429 1430 1431 1432
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end + dsize,
			      btrfs_leaf_data(leaf) + data_end,
			      doff - data_end);
C
Chris Mason 已提交
1433
		for (i = slot + 1; i < nritems; i++) {
C
Chris Mason 已提交
1434
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1435 1436
			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
		}
C
Chris Mason 已提交
1437 1438 1439 1440
		btrfs_memmove(root, leaf, leaf->items + slot,
			      leaf->items + slot + 1,
			      sizeof(struct btrfs_item) *
			      (nritems - slot - 1));
1441
	}
1442 1443
	btrfs_set_header_nritems(&leaf->header, nritems - 1);
	nritems--;
C
Chris Mason 已提交
1444
	/* delete the leaf if we've emptied it */
1445
	if (nritems == 0) {
1446
		if (leaf_buf == root->node) {
1447
			btrfs_set_header_level(&leaf->header, 0);
1448
		} else {
1449
			clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1450
			wait_on_buffer(leaf_buf);
1451
			wret = del_ptr(trans, root, path, 1, path->slots[1]);
C
Chris Mason 已提交
1452 1453
			if (wret)
				ret = wret;
1454
			wret = btrfs_free_extent(trans, root,
C
Chris Mason 已提交
1455
						 leaf_buf->b_blocknr, 1, 1);
C
Chris Mason 已提交
1456 1457
			if (wret)
				ret = wret;
1458
		}
1459
	} else {
1460
		int used = leaf_space_used(leaf, 0, nritems);
C
Chris Mason 已提交
1461
		if (slot == 0) {
1462 1463
			wret = fixup_low_keys(trans, root, path,
					      &leaf->items[0].key, 1);
C
Chris Mason 已提交
1464 1465 1466 1467
			if (wret)
				ret = wret;
		}

C
Chris Mason 已提交
1468
		/* delete the leaf if it is mostly empty */
C
Chris Mason 已提交
1469
		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1470 1471 1472 1473
			/* push_leaf_left fixes the path.
			 * make sure the path still points to our leaf
			 * for possible call to del_ptr below
			 */
1474
			slot = path->slots[1];
C
Chris Mason 已提交
1475
			get_bh(leaf_buf);
1476
			wret = push_leaf_left(trans, root, path, 1);
C
Chris Mason 已提交
1477 1478
			if (wret < 0)
				ret = wret;
1479
			if (path->nodes[0] == leaf_buf &&
1480
			    btrfs_header_nritems(&leaf->header)) {
1481
				wret = push_leaf_right(trans, root, path, 1);
C
Chris Mason 已提交
1482 1483 1484
				if (wret < 0)
					ret = wret;
			}
1485
			if (btrfs_header_nritems(&leaf->header) == 0) {
C
Chris Mason 已提交
1486
				u64 blocknr = leaf_buf->b_blocknr;
1487
				clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1488
				wait_on_buffer(leaf_buf);
1489
				wret = del_ptr(trans, root, path, 1, slot);
C
Chris Mason 已提交
1490 1491
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1492
				btrfs_block_release(root, leaf_buf);
1493 1494
				wret = btrfs_free_extent(trans, root, blocknr,
							 1, 1);
C
Chris Mason 已提交
1495 1496
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1497
			} else {
C
Chris Mason 已提交
1498
				btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1499
				btrfs_block_release(root, leaf_buf);
1500
			}
1501
		} else {
C
Chris Mason 已提交
1502
			btrfs_mark_buffer_dirty(leaf_buf);
1503 1504
		}
	}
C
Chris Mason 已提交
1505
	return ret;
1506 1507
}

C
Chris Mason 已提交
1508 1509
/*
 * walk up the tree as far as required to find the next leaf.
C
Chris Mason 已提交
1510 1511
 * returns 0 if it found something or 1 if there are no greater leaves.
 * returns < 0 on io errors.
C
Chris Mason 已提交
1512
 */
C
Chris Mason 已提交
1513
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1514 1515 1516 1517
{
	int slot;
	int level = 1;
	u64 blocknr;
C
Chris Mason 已提交
1518 1519 1520
	struct buffer_head *c;
	struct btrfs_node *c_node;
	struct buffer_head *next = NULL;
1521

C
Chris Mason 已提交
1522
	while(level < BTRFS_MAX_LEVEL) {
1523
		if (!path->nodes[level])
C
Chris Mason 已提交
1524
			return 1;
1525 1526
		slot = path->slots[level] + 1;
		c = path->nodes[level];
C
Chris Mason 已提交
1527 1528
		c_node = btrfs_buffer_node(c);
		if (slot >= btrfs_header_nritems(&c_node->header)) {
1529 1530 1531
			level++;
			continue;
		}
C
Chris Mason 已提交
1532
		blocknr = btrfs_node_blockptr(c_node, slot);
C
Chris Mason 已提交
1533
		if (next)
C
Chris Mason 已提交
1534
			btrfs_block_release(root, next);
1535 1536 1537 1538 1539 1540 1541
		next = read_tree_block(root, blocknr);
		break;
	}
	path->slots[level] = slot;
	while(1) {
		level--;
		c = path->nodes[level];
C
Chris Mason 已提交
1542
		btrfs_block_release(root, c);
1543 1544 1545 1546
		path->nodes[level] = next;
		path->slots[level] = 0;
		if (!level)
			break;
1547
		next = read_tree_block(root,
C
Chris Mason 已提交
1548
		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1549 1550 1551
	}
	return 0;
}