ctree.c 47.9 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
	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_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) {
76
			btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
77
		}
C
Chris Mason 已提交
78
		btrfs_block_release(root, buf);
C
Chris Mason 已提交
79
	} else {
C
Chris Mason 已提交
80
		btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
81
					bh_blocknr(cow));
C
Chris Mason 已提交
82
		btrfs_mark_buffer_dirty(parent);
83
		btrfs_free_extent(trans, root, bh_blocknr(buf), 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;
C
Chris Mason 已提交
118 119 120 121
	if (k1.flags > k2->flags)
		return 1;
	if (k1.flags < k2->flags)
		return -1;
122 123 124 125
	if (k1.offset > k2->offset)
		return 1;
	if (k1.offset < k2->offset)
		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
{
C
Chris Mason 已提交
203 204 205 206
	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 已提交
207
	if (level == 0)
C
Chris Mason 已提交
208 209
		return check_leaf(root, path, level);
	return check_node(root, path, level);
C
Chris Mason 已提交
210 211
}

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

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

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

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

	if (level == 0)
		return 0;

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

C
Chris Mason 已提交
305
	if (level < BTRFS_MAX_LEVEL - 1)
306 307 308
		parent_buf = path->nodes[level + 1];
	pslot = path->slots[level + 1];

C
Chris Mason 已提交
309 310 311 312
	/*
	 * deal with the case where there is only one pointer in the root
	 * by promoting the node below to a root
	 */
313
	if (!parent_buf) {
C
Chris Mason 已提交
314
		struct buffer_head *child;
315
		u64 blocknr = bh_blocknr(mid_buf);
316

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

C
Chris Mason 已提交
335 336
	if (btrfs_header_nritems(&mid->header) >
	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
337 338 339 340
		return 0;

	left_buf = read_node_slot(root, parent_buf, pslot - 1);
	right_buf = read_node_slot(root, parent_buf, pslot + 1);
341 342

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

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

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

	if (right_buf)
C
Chris Mason 已提交
445
		btrfs_block_release(root, right_buf);
446
	if (left_buf)
C
Chris Mason 已提交
447
		btrfs_block_release(root, left_buf);
448 449 450
	return ret;
}

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

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

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

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

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

599
	if (src_nritems < push_items)
600 601
		push_items = src_nritems;

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

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

658 659
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
660

C
Chris Mason 已提交
661 662
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
C
Chris Mason 已提交
663
	return ret;
664 665
}

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

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

684
	t = btrfs_alloc_free_block(trans, root);
C
Chris Mason 已提交
685
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
686
	memset(c, 0, root->blocksize);
687 688
	btrfs_set_header_nritems(&c->header, 1);
	btrfs_set_header_level(&c->header, level);
689
	btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
690
	btrfs_set_header_generation(&c->header, trans->transid);
C
Chris Mason 已提交
691
	lower = btrfs_buffer_node(path->nodes[level-1]);
C
Chris Mason 已提交
692 693
	memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(c->header.fsid));
694
	if (btrfs_is_leaf(lower))
C
Chris Mason 已提交
695
		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
C
Chris Mason 已提交
696
	else
C
Chris Mason 已提交
697
		lower_key = &lower->ptrs[0].key;
C
Chris Mason 已提交
698 699
	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
		     sizeof(struct btrfs_disk_key));
700
	btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
701

C
Chris Mason 已提交
702
	btrfs_mark_buffer_dirty(t);
703

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

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

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

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

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

C
Chris Mason 已提交
794 795
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(split_buffer);
796
	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
797
			  bh_blocknr(split_buffer), path->slots[level + 1] + 1,
C
Chris Mason 已提交
798
			  level + 1);
C
Chris Mason 已提交
799 800 801
	if (wret)
		ret = wret;

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

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

	if (!nr)
		return 0;
C
Chris Mason 已提交
826 827 828
	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;
829
	WARN_ON(data_len < 0);
830 831 832
	return data_len;
}

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

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

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

	/* update the item pointers */
939 940
	right_nritems += push_items;
	btrfs_set_header_nritems(&right->header, right_nritems);
C
Chris Mason 已提交
941
	push_space = BTRFS_LEAF_DATA_SIZE(root);
942
	for (i = 0; i < right_nritems; i++) {
C
Chris Mason 已提交
943 944 945
		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 已提交
946
	}
947 948
	left_nritems -= push_items;
	btrfs_set_header_nritems(&left->header, left_nritems);
C
Chris Mason 已提交
949

C
Chris Mason 已提交
950 951
	btrfs_mark_buffer_dirty(left_buf);
	btrfs_mark_buffer_dirty(right_buf);
952

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

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

	slot = path->slots[1];
	if (slot == 0) {
		return 1;
	}
	if (!path->nodes[1]) {
		return 1;
	}
C
Chris Mason 已提交
996 997 998
	t = read_tree_block(root,
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
999
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1000
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1001
		btrfs_block_release(root, t);
1002 1003
		return 1;
	}
C
Chris Mason 已提交
1004 1005

	/* cow and double check */
1006
	btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
C
Chris Mason 已提交
1007
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1008
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1009
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1010
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1011 1012 1013
		return 1;
	}

1014 1015 1016 1017 1018 1019
	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++) {
1020 1021 1022
		item = right->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1023 1024
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
1025 1026
			break;
		push_items++;
C
Chris Mason 已提交
1027
		push_space += btrfs_item_size(item) + sizeof(*item);
1028 1029
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1030
		btrfs_block_release(root, t);
1031 1032
		return 1;
	}
1033 1034
	if (push_items == btrfs_header_nritems(&right->header))
		WARN_ON(1);
1035
	/* push data from right to left */
C
Chris Mason 已提交
1036 1037 1038
	btrfs_memcpy(root, left, left->items +
		     btrfs_header_nritems(&left->header),
		     right->items, push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1039
	push_space = BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1040
		     btrfs_item_offset(right->items + push_items -1);
C
Chris Mason 已提交
1041 1042 1043 1044 1045
	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);
1046
	old_left_nritems = btrfs_header_nritems(&left->header);
1047 1048
	BUG_ON(old_left_nritems < 0);

C
Chris Mason 已提交
1049
	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
C
Chris Mason 已提交
1050 1051 1052
		u32 ioff = btrfs_item_offset(left->items + i);
		btrfs_set_item_offset(left->items + i, ioff -
				     (BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1053 1054
				      btrfs_item_offset(left->items +
						        old_left_nritems - 1)));
1055
	}
1056
	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1057 1058

	/* fixup right node */
C
Chris Mason 已提交
1059
	push_space = btrfs_item_offset(right->items + push_items - 1) -
C
Chris Mason 已提交
1060
		     leaf_data_end(root, right);
C
Chris Mason 已提交
1061 1062 1063 1064 1065
	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,
1066
		(btrfs_header_nritems(&right->header) - push_items) *
C
Chris Mason 已提交
1067
		sizeof(struct btrfs_item));
1068 1069 1070
	btrfs_set_header_nritems(&right->header,
				 btrfs_header_nritems(&right->header) -
				 push_items);
C
Chris Mason 已提交
1071
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1072

1073
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1074 1075 1076
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
1077
	}
1078

C
Chris Mason 已提交
1079 1080
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);
1081
	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
C
Chris Mason 已提交
1082 1083
	if (wret)
		ret = wret;
1084 1085 1086 1087

	/* then fixup the leaf pointer in the path */
	if (path->slots[0] < push_items) {
		path->slots[0] += old_left_nritems;
C
Chris Mason 已提交
1088
		btrfs_block_release(root, path->nodes[0]);
1089
		path->nodes[0] = t;
1090 1091
		path->slots[1] -= 1;
	} else {
C
Chris Mason 已提交
1092
		btrfs_block_release(root, t);
1093 1094
		path->slots[0] -= push_items;
	}
1095
	BUG_ON(path->slots[0] < 0);
C
Chris Mason 已提交
1096
	return ret;
1097 1098
}

C
Chris Mason 已提交
1099 1100 1101
/*
 * 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 已提交
1102 1103
 *
 * returns 0 if all went well and < 0 on failure.
C
Chris Mason 已提交
1104
 */
1105
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1106 1107
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size)
1108
{
C
Chris Mason 已提交
1109
	struct buffer_head *l_buf;
C
Chris Mason 已提交
1110
	struct btrfs_leaf *l;
1111
	u32 nritems;
1112 1113
	int mid;
	int slot;
C
Chris Mason 已提交
1114
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1115
	struct buffer_head *right_buffer;
C
Chris Mason 已提交
1116
	int space_needed = data_size + sizeof(struct btrfs_item);
1117 1118 1119
	int data_copy_size;
	int rt_data_off;
	int i;
1120
	int ret = 0;
C
Chris Mason 已提交
1121
	int wret;
1122 1123
	int double_split = 0;
	struct btrfs_disk_key disk_key;
C
Chris Mason 已提交
1124

C
Chris Mason 已提交
1125
	/* first try to make some room by pushing left and right */
1126
	wret = push_leaf_left(trans, root, path, data_size);
C
Chris Mason 已提交
1127 1128 1129
	if (wret < 0)
		return wret;
	if (wret) {
1130
		wret = push_leaf_right(trans, root, path, data_size);
C
Chris Mason 已提交
1131 1132 1133
		if (wret < 0)
			return wret;
	}
C
Chris Mason 已提交
1134
	l_buf = path->nodes[0];
C
Chris Mason 已提交
1135
	l = btrfs_buffer_leaf(l_buf);
C
Chris Mason 已提交
1136 1137

	/* did the pushes work? */
C
Chris Mason 已提交
1138 1139
	if (btrfs_leaf_free_space(root, l) >=
	    sizeof(struct btrfs_item) + data_size)
C
Chris Mason 已提交
1140 1141
		return 0;

C
Chris Mason 已提交
1142
	if (!path->nodes[1]) {
1143
		ret = insert_new_root(trans, root, path, 1);
C
Chris Mason 已提交
1144 1145 1146
		if (ret)
			return ret;
	}
1147
	slot = path->slots[0];
1148
	nritems = btrfs_header_nritems(&l->header);
1149
	mid = (nritems + 1)/ 2;
1150
	right_buffer = btrfs_alloc_free_block(trans, root);
1151
	BUG_ON(!right_buffer);
C
Chris Mason 已提交
1152
	right = btrfs_buffer_leaf(right_buffer);
C
Chris Mason 已提交
1153
	memset(&right->header, 0, sizeof(right->header));
1154
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1155
	btrfs_set_header_generation(&right->header, trans->transid);
1156
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1157 1158
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1159 1160 1161 1162 1163 1164 1165 1166 1167
	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,
1168
						  bh_blocknr(right_buffer),
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
						  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,
1189
						  bh_blocknr(right_buffer),
1190 1191 1192 1193 1194 1195 1196
						  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;
1197 1198 1199 1200 1201 1202
				if (path->slots[1] == 0) {
					wret = fixup_low_keys(trans, root,
					           path, &disk_key, 1);
					if (wret)
						ret = wret;
				}
1203 1204 1205 1206 1207 1208 1209
				return ret;
			}
			mid = slot;
			double_split = 1;
		}
	}
	btrfs_set_header_nritems(&right->header, nritems - mid);
C
Chris Mason 已提交
1210 1211
	data_copy_size = btrfs_item_end(l->items + mid) -
			 leaf_data_end(root, l);
C
Chris Mason 已提交
1212 1213 1214 1215 1216 1217
	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 已提交
1218 1219
	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
		      btrfs_item_end(l->items + mid);
C
Chris Mason 已提交
1220

C
Chris Mason 已提交
1221
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1222
		u32 ioff = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1223 1224
		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
	}
C
Chris Mason 已提交
1225

1226
	btrfs_set_header_nritems(&l->header, mid);
C
Chris Mason 已提交
1227
	ret = 0;
1228
	wret = insert_ptr(trans, root, path, &right->items[0].key,
1229
			  bh_blocknr(right_buffer), path->slots[1] + 1, 1);
C
Chris Mason 已提交
1230 1231
	if (wret)
		ret = wret;
C
Chris Mason 已提交
1232 1233
	btrfs_mark_buffer_dirty(right_buffer);
	btrfs_mark_buffer_dirty(l_buf);
1234
	BUG_ON(path->slots[0] != slot);
1235
	if (mid <= slot) {
C
Chris Mason 已提交
1236
		btrfs_block_release(root, path->nodes[0]);
1237
		path->nodes[0] = right_buffer;
1238 1239
		path->slots[0] -= mid;
		path->slots[1] += 1;
1240
	} else
C
Chris Mason 已提交
1241
		btrfs_block_release(root, right_buffer);
1242
	BUG_ON(path->slots[0] < 0);
1243 1244 1245 1246 1247 1248 1249

	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));
1250
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1251 1252
	btrfs_set_header_generation(&right->header, trans->transid);
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1253 1254
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1255 1256 1257 1258
	btrfs_cpu_key_to_disk(&disk_key, ins_key);
	btrfs_set_header_nritems(&right->header, 0);
	wret = insert_ptr(trans, root, path,
			  &disk_key,
1259
			  bh_blocknr(right_buffer),
1260 1261 1262
			  path->slots[1], 1);
	if (wret)
		ret = wret;
1263 1264 1265 1266 1267
	if (path->slots[1] == 0) {
		wret = fixup_low_keys(trans, root, path, &disk_key, 1);
		if (wret)
			ret = wret;
	}
1268 1269 1270 1271 1272
	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);
1273 1274 1275
	return ret;
}

C
Chris Mason 已提交
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
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;
}

1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
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 已提交
1386 1387 1388 1389
/*
 * 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.
 */
1390 1391 1392
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)
1393
{
C
Chris Mason 已提交
1394
	int ret = 0;
1395
	int slot;
1396
	int slot_orig;
C
Chris Mason 已提交
1397
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1398
	struct buffer_head *leaf_buf;
1399
	u32 nritems;
1400
	unsigned int data_end;
C
Chris Mason 已提交
1401 1402 1403
	struct btrfs_disk_key disk_key;

	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1404

C
Chris Mason 已提交
1405
	/* create a root if there isn't one */
C
Chris Mason 已提交
1406
	if (!root->node)
C
Chris Mason 已提交
1407
		BUG();
1408
	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1409
	if (ret == 0) {
1410
		return -EEXIST;
C
Chris Mason 已提交
1411
	}
1412 1413
	if (ret < 0)
		goto out;
1414

1415 1416
	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1417
	leaf = btrfs_buffer_leaf(leaf_buf);
C
Chris Mason 已提交
1418

1419
	nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
1420
	data_end = leaf_data_end(root, leaf);
1421

C
Chris Mason 已提交
1422
	if (btrfs_leaf_free_space(root, leaf) <
1423
	    sizeof(struct btrfs_item) + data_size) {
1424
		BUG();
1425
	}
1426
	slot = path->slots[0];
1427
	BUG_ON(slot < 0);
1428 1429
	if (slot != nritems) {
		int i;
C
Chris Mason 已提交
1430
		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1431 1432 1433 1434 1435

		/*
		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
		 */
		/* first correct the data pointers */
C
Chris Mason 已提交
1436
		for (i = slot; i < nritems; i++) {
C
Chris Mason 已提交
1437
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1438 1439 1440
			btrfs_set_item_offset(leaf->items + i,
					      ioff - data_size);
		}
1441 1442

		/* shift the items */
C
Chris Mason 已提交
1443 1444 1445
		btrfs_memmove(root, leaf, leaf->items + slot + 1,
			      leaf->items + slot,
			      (nritems - slot) * sizeof(struct btrfs_item));
1446 1447

		/* shift the data */
C
Chris Mason 已提交
1448 1449 1450
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end - data_size, btrfs_leaf_data(leaf) +
			      data_end, old_data - data_end);
1451 1452
		data_end = old_data;
	}
1453
	/* setup the item for the new data */
C
Chris Mason 已提交
1454 1455
	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1456 1457
	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
	btrfs_set_item_size(leaf->items + slot, data_size);
1458
	btrfs_set_header_nritems(&leaf->header, nritems + 1);
C
Chris Mason 已提交
1459
	btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1460 1461

	ret = 0;
1462
	if (slot == 0)
1463
		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
C
Chris Mason 已提交
1464

C
Chris Mason 已提交
1465
	if (btrfs_leaf_free_space(root, leaf) < 0)
1466
		BUG();
1467
	check_leaf(root, path, 0);
1468
out:
1469 1470 1471 1472 1473 1474 1475
	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.
 */
1476 1477 1478
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *cpu_key, void *data, u32
		      data_size)
1479 1480
{
	int ret = 0;
C
Chris Mason 已提交
1481
	struct btrfs_path *path;
1482 1483
	u8 *ptr;

C
Chris Mason 已提交
1484 1485 1486 1487
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
1488
	if (!ret) {
C
Chris Mason 已提交
1489 1490 1491
		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 已提交
1492
			     ptr, data, data_size);
C
Chris Mason 已提交
1493
		btrfs_mark_buffer_dirty(path->nodes[0]);
1494
	}
C
Chris Mason 已提交
1495 1496
	btrfs_release_path(root, path);
	btrfs_free_path(path);
C
Chris Mason 已提交
1497
	return ret;
1498 1499
}

C
Chris Mason 已提交
1500
/*
C
Chris Mason 已提交
1501
 * delete the pointer from a given node.
C
Chris Mason 已提交
1502 1503 1504 1505 1506
 *
 * 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.
 */
1507 1508
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot)
1509
{
C
Chris Mason 已提交
1510
	struct btrfs_node *node;
C
Chris Mason 已提交
1511
	struct buffer_head *parent = path->nodes[level];
1512
	u32 nritems;
C
Chris Mason 已提交
1513
	int ret = 0;
1514
	int wret;
1515

C
Chris Mason 已提交
1516
	node = btrfs_buffer_node(parent);
1517
	nritems = btrfs_header_nritems(&node->header);
1518
	if (slot != nritems -1) {
C
Chris Mason 已提交
1519 1520 1521 1522
		btrfs_memmove(root, node, node->ptrs + slot,
			      node->ptrs + slot + 1,
			      sizeof(struct btrfs_key_ptr) *
			      (nritems - slot - 1));
1523
	}
1524 1525 1526
	nritems--;
	btrfs_set_header_nritems(&node->header, nritems);
	if (nritems == 0 && parent == root->node) {
C
Chris Mason 已提交
1527 1528
		struct btrfs_header *header = btrfs_buffer_header(root->node);
		BUG_ON(btrfs_header_level(header) != 1);
1529
		/* just turn the root into a leaf and break */
C
Chris Mason 已提交
1530
		btrfs_set_header_level(header, 0);
1531
	} else if (slot == 0) {
1532
		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
C
Chris Mason 已提交
1533
				      level + 1);
C
Chris Mason 已提交
1534 1535
		if (wret)
			ret = wret;
1536
	}
C
Chris Mason 已提交
1537
	btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
1538
	return ret;
1539 1540
}

C
Chris Mason 已提交
1541 1542 1543 1544
/*
 * delete the item at the leaf level in path.  If that empties
 * the leaf, remove it from the tree
 */
1545 1546
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path)
1547 1548
{
	int slot;
C
Chris Mason 已提交
1549
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1550
	struct buffer_head *leaf_buf;
1551 1552
	int doff;
	int dsize;
C
Chris Mason 已提交
1553 1554
	int ret = 0;
	int wret;
1555
	u32 nritems;
1556

1557
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1558
	leaf = btrfs_buffer_leaf(leaf_buf);
1559
	slot = path->slots[0];
C
Chris Mason 已提交
1560 1561
	doff = btrfs_item_offset(leaf->items + slot);
	dsize = btrfs_item_size(leaf->items + slot);
1562
	nritems = btrfs_header_nritems(&leaf->header);
1563

1564
	if (slot != nritems - 1) {
1565
		int i;
C
Chris Mason 已提交
1566
		int data_end = leaf_data_end(root, leaf);
C
Chris Mason 已提交
1567 1568 1569 1570
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end + dsize,
			      btrfs_leaf_data(leaf) + data_end,
			      doff - data_end);
C
Chris Mason 已提交
1571
		for (i = slot + 1; i < nritems; i++) {
C
Chris Mason 已提交
1572
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1573 1574
			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
		}
C
Chris Mason 已提交
1575 1576 1577 1578
		btrfs_memmove(root, leaf, leaf->items + slot,
			      leaf->items + slot + 1,
			      sizeof(struct btrfs_item) *
			      (nritems - slot - 1));
1579
	}
1580 1581
	btrfs_set_header_nritems(&leaf->header, nritems - 1);
	nritems--;
C
Chris Mason 已提交
1582
	/* delete the leaf if we've emptied it */
1583
	if (nritems == 0) {
1584
		if (leaf_buf == root->node) {
1585
			btrfs_set_header_level(&leaf->header, 0);
1586
		} else {
1587
			clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1588
			wait_on_buffer(leaf_buf);
1589
			wret = del_ptr(trans, root, path, 1, path->slots[1]);
C
Chris Mason 已提交
1590 1591
			if (wret)
				ret = wret;
1592
			wret = btrfs_free_extent(trans, root,
1593
						 bh_blocknr(leaf_buf), 1, 1);
C
Chris Mason 已提交
1594 1595
			if (wret)
				ret = wret;
1596
		}
1597
	} else {
1598
		int used = leaf_space_used(leaf, 0, nritems);
C
Chris Mason 已提交
1599
		if (slot == 0) {
1600 1601
			wret = fixup_low_keys(trans, root, path,
					      &leaf->items[0].key, 1);
C
Chris Mason 已提交
1602 1603 1604 1605
			if (wret)
				ret = wret;
		}

C
Chris Mason 已提交
1606
		/* delete the leaf if it is mostly empty */
C
Chris Mason 已提交
1607
		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1608 1609 1610 1611
			/* push_leaf_left fixes the path.
			 * make sure the path still points to our leaf
			 * for possible call to del_ptr below
			 */
1612
			slot = path->slots[1];
C
Chris Mason 已提交
1613
			get_bh(leaf_buf);
1614
			wret = push_leaf_left(trans, root, path, 1);
C
Chris Mason 已提交
1615 1616
			if (wret < 0)
				ret = wret;
1617
			if (path->nodes[0] == leaf_buf &&
1618
			    btrfs_header_nritems(&leaf->header)) {
1619
				wret = push_leaf_right(trans, root, path, 1);
C
Chris Mason 已提交
1620 1621 1622
				if (wret < 0)
					ret = wret;
			}
1623
			if (btrfs_header_nritems(&leaf->header) == 0) {
1624
				u64 blocknr = bh_blocknr(leaf_buf);
1625
				clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1626
				wait_on_buffer(leaf_buf);
1627
				wret = del_ptr(trans, root, path, 1, slot);
C
Chris Mason 已提交
1628 1629
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1630
				btrfs_block_release(root, leaf_buf);
1631 1632
				wret = btrfs_free_extent(trans, root, blocknr,
							 1, 1);
C
Chris Mason 已提交
1633 1634
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1635
			} else {
C
Chris Mason 已提交
1636
				btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1637
				btrfs_block_release(root, leaf_buf);
1638
			}
1639
		} else {
C
Chris Mason 已提交
1640
			btrfs_mark_buffer_dirty(leaf_buf);
1641 1642
		}
	}
C
Chris Mason 已提交
1643
	return ret;
1644 1645
}

C
Chris Mason 已提交
1646 1647
/*
 * walk up the tree as far as required to find the next leaf.
C
Chris Mason 已提交
1648 1649
 * returns 0 if it found something or 1 if there are no greater leaves.
 * returns < 0 on io errors.
C
Chris Mason 已提交
1650
 */
C
Chris Mason 已提交
1651
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1652 1653 1654 1655
{
	int slot;
	int level = 1;
	u64 blocknr;
C
Chris Mason 已提交
1656 1657 1658
	struct buffer_head *c;
	struct btrfs_node *c_node;
	struct buffer_head *next = NULL;
1659

C
Chris Mason 已提交
1660
	while(level < BTRFS_MAX_LEVEL) {
1661
		if (!path->nodes[level])
C
Chris Mason 已提交
1662
			return 1;
1663 1664
		slot = path->slots[level] + 1;
		c = path->nodes[level];
C
Chris Mason 已提交
1665 1666
		c_node = btrfs_buffer_node(c);
		if (slot >= btrfs_header_nritems(&c_node->header)) {
1667 1668 1669
			level++;
			continue;
		}
C
Chris Mason 已提交
1670
		blocknr = btrfs_node_blockptr(c_node, slot);
C
Chris Mason 已提交
1671
		if (next)
C
Chris Mason 已提交
1672
			btrfs_block_release(root, next);
1673 1674 1675 1676 1677 1678 1679
		next = read_tree_block(root, blocknr);
		break;
	}
	path->slots[level] = slot;
	while(1) {
		level--;
		c = path->nodes[level];
C
Chris Mason 已提交
1680
		btrfs_block_release(root, c);
1681 1682 1683 1684
		path->nodes[level] = next;
		path->slots[level] = 0;
		if (!level)
			break;
1685
		next = read_tree_block(root,
C
Chris Mason 已提交
1686
		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1687 1688 1689
	}
	return 0;
}