ctree.c 54.6 KB
Newer Older
C
Chris Mason 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

19 20
#include "ctree.h"
#include "disk-io.h"
21
#include "transaction.h"
22

23 24 25
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
26 27
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size);
28
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
29
			  *root, struct buffer_head *dst, struct buffer_head
30 31
			  *src);
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
32 33
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf);
34 35
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot);
36

C
Chris Mason 已提交
37
inline void btrfs_init_path(struct btrfs_path *p)
C
Chris Mason 已提交
38
{
C
Chris Mason 已提交
39
	memset(p, 0, sizeof(*p));
C
Chris Mason 已提交
40 41
}

C
Chris Mason 已提交
42
struct btrfs_path *btrfs_alloc_path(void)
C
Chris Mason 已提交
43
{
C
Chris Mason 已提交
44 45 46 47 48
	struct btrfs_path *path;
	path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
	if (path)
		btrfs_init_path(path);
	return path;
C
Chris Mason 已提交
49 50
}

C
Chris Mason 已提交
51
void btrfs_free_path(struct btrfs_path *p)
52
{
C
Chris Mason 已提交
53 54
	btrfs_release_path(NULL, p);
	kmem_cache_free(btrfs_path_cachep, p);
55 56
}

C
Chris Mason 已提交
57
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
58 59
{
	int i;
C
Chris Mason 已提交
60
	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
61 62
		if (!p->nodes[i])
			break;
C
Chris Mason 已提交
63
		btrfs_block_release(root, p->nodes[i]);
64
	}
C
Chris Mason 已提交
65
	memset(p, 0, sizeof(*p));
66 67
}

68
static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
69 70
			   *root, struct buffer_head *buf, struct buffer_head
			   *parent, int parent_slot, struct buffer_head
71
			   **cow_ret)
C
Chris Mason 已提交
72
{
C
Chris Mason 已提交
73 74
	struct buffer_head *cow;
	struct btrfs_node *cow_node;
75
	int ret;
C
Chris Mason 已提交
76

C
Chris Mason 已提交
77 78 79 80 81 82 83 84 85 86 87
	WARN_ON(!buffer_uptodate(buf));
	if (trans->transaction != root->fs_info->running_transaction) {
		printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
		       root->fs_info->running_transaction->transid);
		WARN_ON(1);
	}
	if (trans->transid != root->fs_info->generation) {
		printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
		       root->fs_info->generation);
		WARN_ON(1);
	}
88 89
	if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
				    trans->transid) {
C
Chris Mason 已提交
90 91 92
		*cow_ret = buf;
		return 0;
	}
93
	cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr);
94 95
	if (IS_ERR(cow))
		return PTR_ERR(cow);
C
Chris Mason 已提交
96
	cow_node = btrfs_buffer_node(cow);
C
Chris Mason 已提交
97 98
	if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
		WARN_ON(1);
C
Chris Mason 已提交
99
	memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
100
	btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow));
101
	btrfs_set_header_generation(&cow_node->header, trans->transid);
102
	btrfs_set_header_owner(&cow_node->header, root->root_key.objectid);
103 104 105
	ret = btrfs_inc_ref(trans, root, buf);
	if (ret)
		return ret;
C
Chris Mason 已提交
106 107
	if (buf == root->node) {
		root->node = cow;
C
Chris Mason 已提交
108
		get_bh(cow);
C
Chris Mason 已提交
109
		if (buf != root->commit_root) {
110
			btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
111
		}
C
Chris Mason 已提交
112
		btrfs_block_release(root, buf);
C
Chris Mason 已提交
113
	} else {
C
Chris Mason 已提交
114
		btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
115
					bh_blocknr(cow));
C
Chris Mason 已提交
116
		btrfs_mark_buffer_dirty(parent);
117
		btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
118
	}
C
Chris Mason 已提交
119
	btrfs_block_release(root, buf);
C
Chris Mason 已提交
120
	btrfs_mark_buffer_dirty(cow);
C
Chris Mason 已提交
121
	*cow_ret = cow;
C
Chris Mason 已提交
122 123 124
	return 0;
}

C
Chris Mason 已提交
125 126 127 128 129
/*
 * 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 已提交
130 131
static inline unsigned int leaf_data_end(struct btrfs_root *root,
					 struct btrfs_leaf *leaf)
132
{
133
	u32 nr = btrfs_header_nritems(&leaf->header);
134
	if (nr == 0)
C
Chris Mason 已提交
135
		return BTRFS_LEAF_DATA_SIZE(root);
C
Chris Mason 已提交
136
	return btrfs_item_offset(leaf->items + nr - 1);
137 138
}

C
Chris Mason 已提交
139 140 141
/*
 * compare two keys in a memcmp fashion
 */
C
Chris Mason 已提交
142
static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
143
{
C
Chris Mason 已提交
144 145 146 147 148
	struct btrfs_key k1;

	btrfs_disk_key_to_cpu(&k1, disk);

	if (k1.objectid > k2->objectid)
149
		return 1;
C
Chris Mason 已提交
150
	if (k1.objectid < k2->objectid)
151
		return -1;
C
Chris Mason 已提交
152 153 154 155
	if (k1.flags > k2->flags)
		return 1;
	if (k1.flags < k2->flags)
		return -1;
156 157 158 159
	if (k1.offset > k2->offset)
		return 1;
	if (k1.offset < k2->offset)
		return -1;
160 161
	return 0;
}
C
Chris Mason 已提交
162

C
Chris Mason 已提交
163 164
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
165
{
C
Chris Mason 已提交
166
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
167
	struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
C
Chris Mason 已提交
168
	int parent_slot;
169 170
	int slot;
	struct btrfs_key cpukey;
171
	u32 nritems = btrfs_header_nritems(&node->header);
C
Chris Mason 已提交
172 173

	if (path->nodes[level + 1])
C
Chris Mason 已提交
174
		parent = btrfs_buffer_node(path->nodes[level + 1]);
A
Aneesh 已提交
175

176
	slot = path->slots[level];
177 178
	BUG_ON(nritems == 0);
	if (parent) {
C
Chris Mason 已提交
179
		struct btrfs_disk_key *parent_key;
A
Aneesh 已提交
180 181

		parent_slot = path->slots[level + 1];
C
Chris Mason 已提交
182 183
		parent_key = &parent->ptrs[parent_slot].key;
		BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
C
Chris Mason 已提交
184
			      sizeof(struct btrfs_disk_key)));
185
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
186
		       btrfs_header_blocknr(&node->header));
C
Chris Mason 已提交
187
	}
C
Chris Mason 已提交
188
	BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
189 190 191 192 193 194 195
	if (slot != 0) {
		btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot - 1].key);
		BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) <= 0);
	}
	if (slot < nritems - 1) {
		btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot + 1].key);
		BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) >= 0);
C
Chris Mason 已提交
196 197 198 199
	}
	return 0;
}

C
Chris Mason 已提交
200 201
static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
202
{
C
Chris Mason 已提交
203
	struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
C
Chris Mason 已提交
204
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
205
	int parent_slot;
206 207 208
	int slot = path->slots[0];
	struct btrfs_key cpukey;

209
	u32 nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
210 211

	if (path->nodes[level + 1])
C
Chris Mason 已提交
212
		parent = btrfs_buffer_node(path->nodes[level + 1]);
A
Aneesh 已提交
213

C
Chris Mason 已提交
214
	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
215 216 217 218 219

	if (nritems == 0)
		return 0;

	if (parent) {
C
Chris Mason 已提交
220
		struct btrfs_disk_key *parent_key;
A
Aneesh 已提交
221 222

		parent_slot = path->slots[level + 1];
C
Chris Mason 已提交
223
		parent_key = &parent->ptrs[parent_slot].key;
C
Chris Mason 已提交
224
		BUG_ON(memcmp(parent_key, &leaf->items[0].key,
C
Chris Mason 已提交
225
		       sizeof(struct btrfs_disk_key)));
226
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
227
		       btrfs_header_blocknr(&leaf->header));
C
Chris Mason 已提交
228
	}
229 230 231 232 233 234 235 236 237 238 239
	if (slot != 0) {
		btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot - 1].key);
		BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) <= 0);
		BUG_ON(btrfs_item_offset(leaf->items + slot - 1) !=
			btrfs_item_end(leaf->items + slot));
	}
	if (slot < nritems - 1) {
		btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot + 1].key);
		BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) >= 0);
		BUG_ON(btrfs_item_offset(leaf->items + slot) !=
			btrfs_item_end(leaf->items + slot + 1));
C
Chris Mason 已提交
240
	}
241 242
	BUG_ON(btrfs_item_offset(leaf->items) +
	       btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root));
C
Chris Mason 已提交
243 244 245
	return 0;
}

C
Chris Mason 已提交
246 247
static int check_block(struct btrfs_root *root, struct btrfs_path *path,
			int level)
C
Chris Mason 已提交
248
{
C
Chris Mason 已提交
249 250 251 252
	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 已提交
253
	if (level == 0)
C
Chris Mason 已提交
254 255
		return check_leaf(root, path, level);
	return check_node(root, path, level);
C
Chris Mason 已提交
256 257
}

C
Chris Mason 已提交
258 259 260 261 262 263 264 265 266
/*
 * 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 已提交
267
static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
268 269 270 271 272 273
		       int max, int *slot)
{
	int low = 0;
	int high = max;
	int mid;
	int ret;
C
Chris Mason 已提交
274
	struct btrfs_disk_key *tmp;
275 276 277

	while(low < high) {
		mid = (low + high) / 2;
C
Chris Mason 已提交
278
		tmp = (struct btrfs_disk_key *)(p + mid * item_size);
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
		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 已提交
294 295 296 297
/*
 * simple bin_search frontend that does the right thing for
 * leaves vs nodes
 */
C
Chris Mason 已提交
298
static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
299
{
300
	if (btrfs_is_leaf(c)) {
C
Chris Mason 已提交
301
		struct btrfs_leaf *l = (struct btrfs_leaf *)c;
C
Chris Mason 已提交
302 303
		return generic_bin_search((void *)l->items,
					  sizeof(struct btrfs_item),
304 305
					  key, btrfs_header_nritems(&c->header),
					  slot);
306
	} else {
C
Chris Mason 已提交
307 308
		return generic_bin_search((void *)c->ptrs,
					  sizeof(struct btrfs_key_ptr),
309 310
					  key, btrfs_header_nritems(&c->header),
					  slot);
311 312 313 314
	}
	return -1;
}

C
Chris Mason 已提交
315 316
static struct buffer_head *read_node_slot(struct btrfs_root *root,
				   struct buffer_head *parent_buf,
317 318
				   int slot)
{
C
Chris Mason 已提交
319
	struct btrfs_node *node = btrfs_buffer_node(parent_buf);
320 321
	if (slot < 0)
		return NULL;
322
	if (slot >= btrfs_header_nritems(&node->header))
323
		return NULL;
324
	return read_tree_block(root, btrfs_node_blockptr(node, slot));
325 326
}

327 328
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
			 *root, struct btrfs_path *path, int level)
329
{
C
Chris Mason 已提交
330 331 332 333
	struct buffer_head *right_buf;
	struct buffer_head *mid_buf;
	struct buffer_head *left_buf;
	struct buffer_head *parent_buf = NULL;
C
Chris Mason 已提交
334 335 336 337
	struct btrfs_node *right = NULL;
	struct btrfs_node *mid;
	struct btrfs_node *left = NULL;
	struct btrfs_node *parent = NULL;
338 339 340 341
	int ret = 0;
	int wret;
	int pslot;
	int orig_slot = path->slots[level];
342
	int err_on_enospc = 0;
343
	u64 orig_ptr;
344 345 346 347 348

	if (level == 0)
		return 0;

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

C
Chris Mason 已提交
352
	if (level < BTRFS_MAX_LEVEL - 1)
353 354 355
		parent_buf = path->nodes[level + 1];
	pslot = path->slots[level + 1];

C
Chris Mason 已提交
356 357 358 359
	/*
	 * deal with the case where there is only one pointer in the root
	 * by promoting the node below to a root
	 */
360
	if (!parent_buf) {
C
Chris Mason 已提交
361
		struct buffer_head *child;
362
		u64 blocknr = bh_blocknr(mid_buf);
363

364
		if (btrfs_header_nritems(&mid->header) != 1)
365 366 367 368 369 370 371
			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 已提交
372 373
		clean_tree_block(trans, root, mid_buf);
		wait_on_buffer(mid_buf);
374
		/* once for the path */
C
Chris Mason 已提交
375
		btrfs_block_release(root, mid_buf);
376
		/* once for the root ptr */
C
Chris Mason 已提交
377
		btrfs_block_release(root, mid_buf);
378
		return btrfs_free_extent(trans, root, blocknr, 1, 1);
379
	}
C
Chris Mason 已提交
380
	parent = btrfs_buffer_node(parent_buf);
381

C
Chris Mason 已提交
382 383
	if (btrfs_header_nritems(&mid->header) >
	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
384 385
		return 0;

386 387 388
	if (btrfs_header_nritems(&mid->header) < 2)
		err_on_enospc = 1;

389 390
	left_buf = read_node_slot(root, parent_buf, pslot - 1);
	right_buf = read_node_slot(root, parent_buf, pslot + 1);
391 392

	/* first, try to make some room in the middle buffer */
393
	if (left_buf) {
394 395 396 397 398 399
		wret = btrfs_cow_block(trans, root, left_buf,
				       parent_buf, pslot - 1, &left_buf);
		if (wret) {
			ret = wret;
			goto enospc;
		}
C
Chris Mason 已提交
400
		left = btrfs_buffer_node(left_buf);
401
		orig_slot += btrfs_header_nritems(&left->header);
402
		wret = push_node_left(trans, root, left_buf, mid_buf);
403 404
		if (wret < 0)
			ret = wret;
405 406
		if (btrfs_header_nritems(&mid->header) < 2)
			err_on_enospc = 1;
407
	}
408 409 410 411

	/*
	 * then try to empty the right most buffer into the middle
	 */
412
	if (right_buf) {
413 414 415 416 417 418 419
		wret = btrfs_cow_block(trans, root, right_buf,
				       parent_buf, pslot + 1, &right_buf);
		if (wret) {
			ret = wret;
			goto enospc;
		}

C
Chris Mason 已提交
420
		right = btrfs_buffer_node(right_buf);
421
		wret = push_node_left(trans, root, mid_buf, right_buf);
422
		if (wret < 0 && wret != -ENOSPC)
423
			ret = wret;
424
		if (btrfs_header_nritems(&right->header) == 0) {
425
			u64 blocknr = bh_blocknr(right_buf);
426
			clean_tree_block(trans, root, right_buf);
C
Chris Mason 已提交
427 428
			wait_on_buffer(right_buf);
			btrfs_block_release(root, right_buf);
429 430
			right_buf = NULL;
			right = NULL;
431 432
			wret = del_ptr(trans, root, path, level + 1, pslot +
				       1);
433 434
			if (wret)
				ret = wret;
435
			wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
436 437 438
			if (wret)
				ret = wret;
		} else {
C
Chris Mason 已提交
439 440 441 442 443
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot + 1].key,
				     &right->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
444 445
		}
	}
446
	if (btrfs_header_nritems(&mid->header) == 1) {
447 448 449 450 451 452 453 454 455 456
		/*
		 * 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);
457
		wret = balance_node_right(trans, root, mid_buf, left_buf);
458
		if (wret < 0) {
459
			ret = wret;
460 461
			goto enospc;
		}
462 463
		BUG_ON(wret == 1);
	}
464
	if (btrfs_header_nritems(&mid->header) == 0) {
465
		/* we've managed to empty the middle node, drop it */
466
		u64 blocknr = bh_blocknr(mid_buf);
467
		clean_tree_block(trans, root, mid_buf);
C
Chris Mason 已提交
468 469
		wait_on_buffer(mid_buf);
		btrfs_block_release(root, mid_buf);
470 471
		mid_buf = NULL;
		mid = NULL;
472
		wret = del_ptr(trans, root, path, level + 1, pslot);
473 474
		if (wret)
			ret = wret;
475
		wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
476 477
		if (wret)
			ret = wret;
478 479
	} else {
		/* update the parent key to reflect our changes */
C
Chris Mason 已提交
480 481 482 483
		btrfs_memcpy(root, parent,
			     &parent->ptrs[pslot].key, &mid->ptrs[0].key,
			     sizeof(struct btrfs_disk_key));
		btrfs_mark_buffer_dirty(parent_buf);
484
	}
485

486
	/* update the path */
487
	if (left_buf) {
488
		if (btrfs_header_nritems(&left->header) > orig_slot) {
C
Chris Mason 已提交
489
			get_bh(left_buf);
490 491 492 493
			path->nodes[level] = left_buf;
			path->slots[level + 1] -= 1;
			path->slots[level] = orig_slot;
			if (mid_buf)
C
Chris Mason 已提交
494
				btrfs_block_release(root, mid_buf);
495
		} else {
496
			orig_slot -= btrfs_header_nritems(&left->header);
497 498 499
			path->slots[level] = orig_slot;
		}
	}
500
	/* double check we haven't messed things up */
C
Chris Mason 已提交
501
	check_block(root, path, level);
C
Chris Mason 已提交
502 503 504
	if (orig_ptr !=
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
				path->slots[level]))
505
		BUG();
506
enospc:
507
	if (right_buf)
C
Chris Mason 已提交
508
		btrfs_block_release(root, right_buf);
509
	if (left_buf)
C
Chris Mason 已提交
510
		btrfs_block_release(root, left_buf);
511 512 513
	return ret;
}

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
/* returns zero if the push worked, non-zero otherwise */
static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
				struct btrfs_root *root,
				struct btrfs_path *path, int level)
{
	struct buffer_head *right_buf;
	struct buffer_head *mid_buf;
	struct buffer_head *left_buf;
	struct buffer_head *parent_buf = NULL;
	struct btrfs_node *right = NULL;
	struct btrfs_node *mid;
	struct btrfs_node *left = NULL;
	struct btrfs_node *parent = NULL;
	int ret = 0;
	int wret;
	int pslot;
	int orig_slot = path->slots[level];
	u64 orig_ptr;

	if (level == 0)
		return 1;

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

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

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

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

	/* first, try to make some room in the middle buffer */
	if (left_buf) {
		u32 left_nr;
		left = btrfs_buffer_node(left_buf);
		left_nr = btrfs_header_nritems(&left->header);
C
Chris Mason 已提交
555 556 557
		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
558 559 560 561 562 563 564 565 566
			ret = btrfs_cow_block(trans, root, left_buf, parent_buf,
					      pslot - 1, &left_buf);
			if (ret)
				wret = 1;
			else {
				left = btrfs_buffer_node(left_buf);
				wret = push_node_left(trans, root,
						      left_buf, mid_buf);
			}
C
Chris Mason 已提交
567
		}
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
		if (wret < 0)
			ret = wret;
		if (wret == 0) {
			orig_slot += left_nr;
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot].key,
				     &mid->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
			if (btrfs_header_nritems(&left->header) > orig_slot) {
				path->nodes[level] = left_buf;
				path->slots[level + 1] -= 1;
				path->slots[level] = orig_slot;
				btrfs_block_release(root, mid_buf);
			} else {
				orig_slot -=
					btrfs_header_nritems(&left->header);
				path->slots[level] = orig_slot;
				btrfs_block_release(root, left_buf);
			}
			check_node(root, path, level);
			return 0;
		}
		btrfs_block_release(root, left_buf);
	}
	right_buf = read_node_slot(root, parent_buf, pslot + 1);

	/*
	 * then try to empty the right most buffer into the middle
	 */
	if (right_buf) {
C
Chris Mason 已提交
599
		u32 right_nr;
600
		right = btrfs_buffer_node(right_buf);
C
Chris Mason 已提交
601 602 603 604
		right_nr = btrfs_header_nritems(&right->header);
		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
605 606 607 608 609 610 611 612 613 614
			ret = btrfs_cow_block(trans, root, right_buf,
					      parent_buf, pslot + 1,
					      &right_buf);
			if (ret)
				wret = 1;
			else {
				right = btrfs_buffer_node(right_buf);
				wret = balance_node_right(trans, root,
							  right_buf, mid_buf);
			}
C
Chris Mason 已提交
615
		}
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
		if (wret < 0)
			ret = wret;
		if (wret == 0) {
			btrfs_memcpy(root, parent,
				     &parent->ptrs[pslot + 1].key,
				     &right->ptrs[0].key,
				     sizeof(struct btrfs_disk_key));
			btrfs_mark_buffer_dirty(parent_buf);
			if (btrfs_header_nritems(&mid->header) <= orig_slot) {
				path->nodes[level] = right_buf;
				path->slots[level + 1] += 1;
				path->slots[level] = orig_slot -
					btrfs_header_nritems(&mid->header);
				btrfs_block_release(root, mid_buf);
			} else {
				btrfs_block_release(root, right_buf);
			}
			check_node(root, path, level);
			return 0;
		}
		btrfs_block_release(root, right_buf);
	}
	check_node(root, path, level);
	return 1;
}

C
Chris Mason 已提交
642 643 644 645 646 647
/*
 * 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 已提交
648 649
 * be inserted, and 1 is returned.  If there are other errors during the
 * search a negative error number is returned.
C
Chris Mason 已提交
650 651 652 653
 *
 * 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 已提交
654
 */
655 656 657
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)
658
{
C
Chris Mason 已提交
659 660
	struct buffer_head *b;
	struct buffer_head *cow_buf;
C
Chris Mason 已提交
661
	struct btrfs_node *c;
662
	struct btrfs_root_item *root_item = &root->root_item;
663 664 665
	int slot;
	int ret;
	int level;
666 667 668 669 670 671
	u8 lowest_level = 0;

	if (btrfs_root_refs(root_item) == 0 && root->ref_cows) {
		lowest_level = root_item->drop_level;
		WARN_ON(ins_len || cow);
	}
C
Chris Mason 已提交
672

C
Chris Mason 已提交
673 674
	WARN_ON(p->nodes[0] != NULL);
	WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
675 676
again:
	b = root->node;
C
Chris Mason 已提交
677
	get_bh(b);
678
	while (b) {
C
Chris Mason 已提交
679 680
		c = btrfs_buffer_node(b);
		level = btrfs_header_level(&c->header);
C
Chris Mason 已提交
681 682
		if (cow) {
			int wret;
C
Chris Mason 已提交
683 684 685
			wret = btrfs_cow_block(trans, root, b,
					       p->nodes[level + 1],
					       p->slots[level + 1],
686
					       &cow_buf);
687 688 689 690
			if (wret) {
				btrfs_block_release(root, cow_buf);
				return wret;
			}
C
Chris Mason 已提交
691
			b = cow_buf;
C
Chris Mason 已提交
692
			c = btrfs_buffer_node(b);
C
Chris Mason 已提交
693 694
		}
		BUG_ON(!cow && ins_len);
C
Chris Mason 已提交
695 696 697
		if (level != btrfs_header_level(&c->header))
			WARN_ON(1);
		level = btrfs_header_level(&c->header);
698
		p->nodes[level] = b;
C
Chris Mason 已提交
699
		ret = check_block(root, p, level);
C
Chris Mason 已提交
700 701
		if (ret)
			return -1;
702
		ret = bin_search(c, key, &slot);
703
		if (!btrfs_is_leaf(c)) {
704 705 706
			if (ret && slot > 0)
				slot -= 1;
			p->slots[level] = slot;
707 708
			if (ins_len > 0 && btrfs_header_nritems(&c->header) >=
			    BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
709
				int sret = split_node(trans, root, p, level);
C
Chris Mason 已提交
710 711 712 713
				BUG_ON(sret > 0);
				if (sret)
					return sret;
				b = p->nodes[level];
C
Chris Mason 已提交
714
				c = btrfs_buffer_node(b);
C
Chris Mason 已提交
715
				slot = p->slots[level];
716
			} else if (ins_len < 0) {
717 718
				int sret = balance_level(trans, root, p,
							 level);
719 720 721 722 723
				if (sret)
					return sret;
				b = p->nodes[level];
				if (!b)
					goto again;
C
Chris Mason 已提交
724
				c = btrfs_buffer_node(b);
725
				slot = p->slots[level];
726
				BUG_ON(btrfs_header_nritems(&c->header) == 1);
C
Chris Mason 已提交
727
			}
728 729 730
			/* this is only true while dropping a snapshot */
			if (level == lowest_level)
				break;
731
			b = read_tree_block(root, btrfs_node_blockptr(c, slot));
732
		} else {
C
Chris Mason 已提交
733
			struct btrfs_leaf *l = (struct btrfs_leaf *)c;
734
			p->slots[level] = slot;
C
Chris Mason 已提交
735
			if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
C
Chris Mason 已提交
736
			    sizeof(struct btrfs_item) + ins_len) {
737 738
				int sret = split_leaf(trans, root, key,
						      p, ins_len);
C
Chris Mason 已提交
739 740 741 742
				BUG_ON(sret > 0);
				if (sret)
					return sret;
			}
743 744 745
			return ret;
		}
	}
C
Chris Mason 已提交
746
	return 1;
747 748
}

C
Chris Mason 已提交
749 750 751 752 753 754
/*
 * 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 已提交
755 756 757
 *
 * 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 已提交
758
 */
759 760 761
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)
762 763
{
	int i;
C
Chris Mason 已提交
764
	int ret = 0;
C
Chris Mason 已提交
765 766
	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
		struct btrfs_node *t;
767
		int tslot = path->slots[i];
768
		if (!path->nodes[i])
769
			break;
C
Chris Mason 已提交
770
		t = btrfs_buffer_node(path->nodes[i]);
C
Chris Mason 已提交
771 772
		btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
		btrfs_mark_buffer_dirty(path->nodes[i]);
773 774 775
		if (tslot != 0)
			break;
	}
C
Chris Mason 已提交
776
	return ret;
777 778
}

C
Chris Mason 已提交
779 780
/*
 * try to push data from one node into the next node left in the
781
 * tree.
C
Chris Mason 已提交
782 783 784
 *
 * 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 已提交
785
 */
786
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
787 788
			  *root, struct buffer_head *dst_buf, struct
			  buffer_head *src_buf)
789
{
C
Chris Mason 已提交
790 791
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
792
	int push_items = 0;
793 794
	int src_nritems;
	int dst_nritems;
C
Chris Mason 已提交
795
	int ret = 0;
796

797 798
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
799
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
800

801
	if (push_items <= 0) {
802
		return 1;
803
	}
804

805
	if (src_nritems < push_items)
806 807
		push_items = src_nritems;

C
Chris Mason 已提交
808 809
	btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
		     push_items * sizeof(struct btrfs_key_ptr));
810
	if (push_items < src_nritems) {
C
Chris Mason 已提交
811
		btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
C
Chris Mason 已提交
812
			(src_nritems - push_items) *
C
Chris Mason 已提交
813
			sizeof(struct btrfs_key_ptr));
814
	}
815 816
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
C
Chris Mason 已提交
817 818
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
819 820 821 822 823 824 825 826 827 828 829 830
	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
 */
831
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
832 833
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf)
834
{
C
Chris Mason 已提交
835 836
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
837 838 839 840 841 842
	int push_items = 0;
	int max_push;
	int src_nritems;
	int dst_nritems;
	int ret = 0;

843 844
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
845
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
846 847 848 849 850 851 852 853 854 855 856
	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 已提交
857 858 859 860 861 862
	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));
863

864 865
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
866

C
Chris Mason 已提交
867 868
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
C
Chris Mason 已提交
869
	return ret;
870 871
}

C
Chris Mason 已提交
872 873 874 875
/*
 * 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 已提交
876 877
 *
 * returns zero on success or < 0 on failure.
C
Chris Mason 已提交
878
 */
879 880
static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int level)
C
Chris Mason 已提交
881
{
C
Chris Mason 已提交
882
	struct buffer_head *t;
C
Chris Mason 已提交
883 884
	struct btrfs_node *lower;
	struct btrfs_node *c;
C
Chris Mason 已提交
885
	struct btrfs_disk_key *lower_key;
C
Chris Mason 已提交
886 887 888 889

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

890
	t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr);
891 892
	if (IS_ERR(t))
		return PTR_ERR(t);
C
Chris Mason 已提交
893
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
894
	memset(c, 0, root->blocksize);
895 896
	btrfs_set_header_nritems(&c->header, 1);
	btrfs_set_header_level(&c->header, level);
897
	btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
898
	btrfs_set_header_generation(&c->header, trans->transid);
899
	btrfs_set_header_owner(&c->header, root->root_key.objectid);
C
Chris Mason 已提交
900
	lower = btrfs_buffer_node(path->nodes[level-1]);
C
Chris Mason 已提交
901 902
	memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(c->header.fsid));
903
	if (btrfs_is_leaf(lower))
C
Chris Mason 已提交
904
		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
C
Chris Mason 已提交
905
	else
C
Chris Mason 已提交
906
		lower_key = &lower->ptrs[0].key;
C
Chris Mason 已提交
907 908
	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
		     sizeof(struct btrfs_disk_key));
909
	btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
910

C
Chris Mason 已提交
911
	btrfs_mark_buffer_dirty(t);
912

C
Chris Mason 已提交
913
	/* the super has an extra ref to root->node */
C
Chris Mason 已提交
914
	btrfs_block_release(root, root->node);
C
Chris Mason 已提交
915
	root->node = t;
C
Chris Mason 已提交
916
	get_bh(t);
C
Chris Mason 已提交
917 918 919 920 921
	path->nodes[level] = t;
	path->slots[level] = 0;
	return 0;
}

C
Chris Mason 已提交
922 923 924
/*
 * worker function to insert a single pointer in a node.
 * the node should have enough room for the pointer already
C
Chris Mason 已提交
925
 *
C
Chris Mason 已提交
926 927
 * slot and level indicate where you want the key to go, and
 * blocknr is the block the key points to.
C
Chris Mason 已提交
928 929
 *
 * returns zero on success and < 0 on any error
C
Chris Mason 已提交
930
 */
931 932 933
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 已提交
934
{
C
Chris Mason 已提交
935
	struct btrfs_node *lower;
C
Chris Mason 已提交
936
	int nritems;
C
Chris Mason 已提交
937 938

	BUG_ON(!path->nodes[level]);
C
Chris Mason 已提交
939
	lower = btrfs_buffer_node(path->nodes[level]);
940
	nritems = btrfs_header_nritems(&lower->header);
C
Chris Mason 已提交
941 942
	if (slot > nritems)
		BUG();
C
Chris Mason 已提交
943
	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
C
Chris Mason 已提交
944 945
		BUG();
	if (slot != nritems) {
C
Chris Mason 已提交
946 947 948
		btrfs_memmove(root, lower, lower->ptrs + slot + 1,
			      lower->ptrs + slot,
			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
C
Chris Mason 已提交
949
	}
C
Chris Mason 已提交
950 951
	btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
		     key, sizeof(struct btrfs_disk_key));
952
	btrfs_set_node_blockptr(lower, slot, blocknr);
953
	btrfs_set_header_nritems(&lower->header, nritems + 1);
C
Chris Mason 已提交
954
	btrfs_mark_buffer_dirty(path->nodes[level]);
955
	check_node(root, path, level);
C
Chris Mason 已提交
956 957 958
	return 0;
}

C
Chris Mason 已提交
959 960 961 962 963 964
/*
 * 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 已提交
965 966
 *
 * returns 0 on success and < 0 on failure
C
Chris Mason 已提交
967
 */
968 969
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, int level)
970
{
C
Chris Mason 已提交
971
	struct buffer_head *t;
C
Chris Mason 已提交
972
	struct btrfs_node *c;
C
Chris Mason 已提交
973
	struct buffer_head *split_buffer;
C
Chris Mason 已提交
974
	struct btrfs_node *split;
975
	int mid;
C
Chris Mason 已提交
976
	int ret;
C
Chris Mason 已提交
977
	int wret;
978
	u32 c_nritems;
979

C
Chris Mason 已提交
980
	t = path->nodes[level];
C
Chris Mason 已提交
981
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
982 983
	if (t == root->node) {
		/* trying to split the root, lets make a new one */
984
		ret = insert_new_root(trans, root, path, level + 1);
C
Chris Mason 已提交
985 986
		if (ret)
			return ret;
987 988 989 990 991 992 993 994
	} else {
		ret = push_nodes_for_insert(trans, root, path, level);
		t = path->nodes[level];
		c = btrfs_buffer_node(t);
		if (!ret &&
		    btrfs_header_nritems(&c->header) <
		    BTRFS_NODEPTRS_PER_BLOCK(root) - 1)
			return 0;
995 996
		if (ret < 0)
			return ret;
997
	}
998

999
	c_nritems = btrfs_header_nritems(&c->header);
1000
	split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr);
1001 1002 1003
	if (IS_ERR(split_buffer))
		return PTR_ERR(split_buffer);

C
Chris Mason 已提交
1004
	split = btrfs_buffer_node(split_buffer);
1005
	btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
1006
	btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
1007
	btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer));
1008
	btrfs_set_header_generation(&split->header, trans->transid);
1009
	btrfs_set_header_owner(&split->header, root->root_key.objectid);
C
Chris Mason 已提交
1010 1011
	memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(split->header.fsid));
1012
	mid = (c_nritems + 1) / 2;
C
Chris Mason 已提交
1013 1014
	btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
		     (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
1015 1016
	btrfs_set_header_nritems(&split->header, c_nritems - mid);
	btrfs_set_header_nritems(&c->header, mid);
C
Chris Mason 已提交
1017 1018
	ret = 0;

C
Chris Mason 已提交
1019 1020
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(split_buffer);
1021
	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
1022
			  bh_blocknr(split_buffer), path->slots[level + 1] + 1,
C
Chris Mason 已提交
1023
			  level + 1);
C
Chris Mason 已提交
1024 1025 1026
	if (wret)
		ret = wret;

C
Chris Mason 已提交
1027
	if (path->slots[level] >= mid) {
C
Chris Mason 已提交
1028
		path->slots[level] -= mid;
C
Chris Mason 已提交
1029
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1030 1031 1032
		path->nodes[level] = split_buffer;
		path->slots[level + 1] += 1;
	} else {
C
Chris Mason 已提交
1033
		btrfs_block_release(root, split_buffer);
1034
	}
C
Chris Mason 已提交
1035
	return ret;
1036 1037
}

C
Chris Mason 已提交
1038 1039 1040 1041 1042
/*
 * 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 已提交
1043
static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
1044 1045
{
	int data_len;
1046 1047
	int nritems = btrfs_header_nritems(&l->header);
	int end = min(nritems, start + nr) - 1;
1048 1049 1050

	if (!nr)
		return 0;
C
Chris Mason 已提交
1051 1052 1053
	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;
1054
	WARN_ON(data_len < 0);
1055 1056 1057
	return data_len;
}

1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
/*
 * 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 已提交
1069 1070 1071
/*
 * 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 已提交
1072 1073 1074
 *
 * 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 已提交
1075
 */
1076 1077
static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int data_size)
C
Chris Mason 已提交
1078
{
C
Chris Mason 已提交
1079 1080
	struct buffer_head *left_buf = path->nodes[0];
	struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
C
Chris Mason 已提交
1081
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1082 1083 1084
	struct buffer_head *right_buf;
	struct buffer_head *upper;
	struct btrfs_node *upper_node;
C
Chris Mason 已提交
1085 1086 1087 1088 1089
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1090
	struct btrfs_item *item;
1091 1092
	u32 left_nritems;
	u32 right_nritems;
1093
	int ret;
C
Chris Mason 已提交
1094 1095 1096 1097 1098 1099

	slot = path->slots[1];
	if (!path->nodes[1]) {
		return 1;
	}
	upper = path->nodes[1];
C
Chris Mason 已提交
1100 1101
	upper_node = btrfs_buffer_node(upper);
	if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
C
Chris Mason 已提交
1102 1103
		return 1;
	}
C
Chris Mason 已提交
1104 1105 1106
	right_buf = read_tree_block(root,
		    btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1107
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1108
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1109
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1110 1111
		return 1;
	}
C
Chris Mason 已提交
1112
	/* cow and double check */
1113 1114 1115 1116 1117 1118
	ret = btrfs_cow_block(trans, root, right_buf, upper,
			      slot + 1, &right_buf);
	if (ret) {
		btrfs_block_release(root, right_buf);
		return 1;
	}
C
Chris Mason 已提交
1119
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1120
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1121
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1122
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1123 1124 1125
		return 1;
	}

1126
	left_nritems = btrfs_header_nritems(&left->header);
1127 1128 1129 1130 1131
	if (left_nritems == 0) {
		btrfs_block_release(root, right_buf);
		return 1;
	}
	for (i = left_nritems - 1; i >= 1; i--) {
C
Chris Mason 已提交
1132 1133 1134
		item = left->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1135 1136
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
C
Chris Mason 已提交
1137 1138
			break;
		push_items++;
C
Chris Mason 已提交
1139
		push_space += btrfs_item_size(item) + sizeof(*item);
C
Chris Mason 已提交
1140 1141
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1142
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1143 1144
		return 1;
	}
1145 1146
	if (push_items == left_nritems)
		WARN_ON(1);
1147
	right_nritems = btrfs_header_nritems(&right->header);
C
Chris Mason 已提交
1148
	/* push left to right */
C
Chris Mason 已提交
1149
	push_space = btrfs_item_end(left->items + left_nritems - push_items);
C
Chris Mason 已提交
1150
	push_space -= leaf_data_end(root, left);
C
Chris Mason 已提交
1151
	/* make room in the right data area */
C
Chris Mason 已提交
1152 1153 1154 1155 1156
	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 已提交
1157
	/* copy from the left data area */
C
Chris Mason 已提交
1158 1159 1160 1161 1162
	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 已提交
1163
		right_nritems * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1164
	/* copy the items from left to right */
C
Chris Mason 已提交
1165 1166 1167
	btrfs_memcpy(root, right, right->items, left->items +
		     left_nritems - push_items,
		     push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1168 1169

	/* update the item pointers */
1170 1171
	right_nritems += push_items;
	btrfs_set_header_nritems(&right->header, right_nritems);
C
Chris Mason 已提交
1172
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1173
	for (i = 0; i < right_nritems; i++) {
C
Chris Mason 已提交
1174 1175 1176
		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 已提交
1177
	}
1178 1179
	left_nritems -= push_items;
	btrfs_set_header_nritems(&left->header, left_nritems);
C
Chris Mason 已提交
1180

C
Chris Mason 已提交
1181 1182
	btrfs_mark_buffer_dirty(left_buf);
	btrfs_mark_buffer_dirty(right_buf);
1183

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

C
Chris Mason 已提交
1188
	/* then fixup the leaf pointer in the path */
1189 1190
	if (path->slots[0] >= left_nritems) {
		path->slots[0] -= left_nritems;
C
Chris Mason 已提交
1191
		btrfs_block_release(root, path->nodes[0]);
C
Chris Mason 已提交
1192 1193 1194
		path->nodes[0] = right_buf;
		path->slots[1] += 1;
	} else {
C
Chris Mason 已提交
1195
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1196
	}
1197 1198
	if (path->nodes[1])
		check_node(root, path, 1);
C
Chris Mason 已提交
1199 1200
	return 0;
}
C
Chris Mason 已提交
1201 1202 1203 1204
/*
 * 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
 */
1205 1206
static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int data_size)
1207
{
C
Chris Mason 已提交
1208 1209 1210
	struct buffer_head *right_buf = path->nodes[0];
	struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
	struct buffer_head *t;
C
Chris Mason 已提交
1211
	struct btrfs_leaf *left;
1212 1213 1214 1215 1216
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1217
	struct btrfs_item *item;
1218
	u32 old_left_nritems;
C
Chris Mason 已提交
1219 1220
	int ret = 0;
	int wret;
1221 1222 1223 1224 1225 1226 1227 1228

	slot = path->slots[1];
	if (slot == 0) {
		return 1;
	}
	if (!path->nodes[1]) {
		return 1;
	}
C
Chris Mason 已提交
1229 1230 1231
	t = read_tree_block(root,
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1232
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1233
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1234
		btrfs_block_release(root, t);
1235 1236
		return 1;
	}
C
Chris Mason 已提交
1237 1238

	/* cow and double check */
1239 1240 1241 1242 1243
	ret = btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
	if (ret) {
		/* we hit -ENOSPC, but it isn't fatal here */
		return 1;
	}
C
Chris Mason 已提交
1244
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1245
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1246
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1247
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1248 1249 1250
		return 1;
	}

1251 1252 1253 1254 1255 1256
	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++) {
1257 1258 1259
		item = right->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1260 1261
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
1262 1263
			break;
		push_items++;
C
Chris Mason 已提交
1264
		push_space += btrfs_item_size(item) + sizeof(*item);
1265 1266
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1267
		btrfs_block_release(root, t);
1268 1269
		return 1;
	}
1270 1271
	if (push_items == btrfs_header_nritems(&right->header))
		WARN_ON(1);
1272
	/* push data from right to left */
C
Chris Mason 已提交
1273 1274 1275
	btrfs_memcpy(root, left, left->items +
		     btrfs_header_nritems(&left->header),
		     right->items, push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1276
	push_space = BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1277
		     btrfs_item_offset(right->items + push_items -1);
C
Chris Mason 已提交
1278 1279 1280 1281 1282
	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);
1283
	old_left_nritems = btrfs_header_nritems(&left->header);
1284 1285
	BUG_ON(old_left_nritems < 0);

C
Chris Mason 已提交
1286
	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
C
Chris Mason 已提交
1287 1288 1289
		u32 ioff = btrfs_item_offset(left->items + i);
		btrfs_set_item_offset(left->items + i, ioff -
				     (BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1290 1291
				      btrfs_item_offset(left->items +
						        old_left_nritems - 1)));
1292
	}
1293
	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1294 1295

	/* fixup right node */
C
Chris Mason 已提交
1296
	push_space = btrfs_item_offset(right->items + push_items - 1) -
C
Chris Mason 已提交
1297
		     leaf_data_end(root, right);
C
Chris Mason 已提交
1298 1299 1300 1301 1302
	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,
1303
		(btrfs_header_nritems(&right->header) - push_items) *
C
Chris Mason 已提交
1304
		sizeof(struct btrfs_item));
1305 1306 1307
	btrfs_set_header_nritems(&right->header,
				 btrfs_header_nritems(&right->header) -
				 push_items);
C
Chris Mason 已提交
1308
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1309

1310
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1311 1312 1313
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
1314
	}
1315

C
Chris Mason 已提交
1316 1317
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);
1318

1319
	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
C
Chris Mason 已提交
1320 1321
	if (wret)
		ret = wret;
1322 1323 1324 1325

	/* then fixup the leaf pointer in the path */
	if (path->slots[0] < push_items) {
		path->slots[0] += old_left_nritems;
C
Chris Mason 已提交
1326
		btrfs_block_release(root, path->nodes[0]);
1327
		path->nodes[0] = t;
1328 1329
		path->slots[1] -= 1;
	} else {
C
Chris Mason 已提交
1330
		btrfs_block_release(root, t);
1331 1332
		path->slots[0] -= push_items;
	}
1333
	BUG_ON(path->slots[0] < 0);
1334 1335
	if (path->nodes[1])
		check_node(root, path, 1);
C
Chris Mason 已提交
1336
	return ret;
1337 1338
}

C
Chris Mason 已提交
1339 1340 1341
/*
 * 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 已提交
1342 1343
 *
 * returns 0 if all went well and < 0 on failure.
C
Chris Mason 已提交
1344
 */
1345
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1346 1347
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size)
1348
{
C
Chris Mason 已提交
1349
	struct buffer_head *l_buf;
C
Chris Mason 已提交
1350
	struct btrfs_leaf *l;
1351
	u32 nritems;
1352 1353
	int mid;
	int slot;
C
Chris Mason 已提交
1354
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1355
	struct buffer_head *right_buffer;
C
Chris Mason 已提交
1356
	int space_needed = data_size + sizeof(struct btrfs_item);
1357 1358 1359
	int data_copy_size;
	int rt_data_off;
	int i;
1360
	int ret = 0;
C
Chris Mason 已提交
1361
	int wret;
1362 1363
	int double_split = 0;
	struct btrfs_disk_key disk_key;
C
Chris Mason 已提交
1364

C
Chris Mason 已提交
1365
	/* first try to make some room by pushing left and right */
1366
	wret = push_leaf_left(trans, root, path, data_size);
C
Chris Mason 已提交
1367 1368 1369
	if (wret < 0)
		return wret;
	if (wret) {
1370
		wret = push_leaf_right(trans, root, path, data_size);
C
Chris Mason 已提交
1371 1372 1373
		if (wret < 0)
			return wret;
	}
C
Chris Mason 已提交
1374
	l_buf = path->nodes[0];
C
Chris Mason 已提交
1375
	l = btrfs_buffer_leaf(l_buf);
C
Chris Mason 已提交
1376 1377

	/* did the pushes work? */
C
Chris Mason 已提交
1378 1379
	if (btrfs_leaf_free_space(root, l) >=
	    sizeof(struct btrfs_item) + data_size)
C
Chris Mason 已提交
1380 1381
		return 0;

C
Chris Mason 已提交
1382
	if (!path->nodes[1]) {
1383
		ret = insert_new_root(trans, root, path, 1);
C
Chris Mason 已提交
1384 1385 1386
		if (ret)
			return ret;
	}
1387
	slot = path->slots[0];
1388
	nritems = btrfs_header_nritems(&l->header);
1389
	mid = (nritems + 1)/ 2;
1390

1391
	right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
1392 1393 1394
	if (IS_ERR(right_buffer))
		return PTR_ERR(right_buffer);

C
Chris Mason 已提交
1395
	right = btrfs_buffer_leaf(right_buffer);
C
Chris Mason 已提交
1396
	memset(&right->header, 0, sizeof(right->header));
1397
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1398
	btrfs_set_header_generation(&right->header, trans->transid);
1399
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1400
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1401 1402
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1403 1404 1405 1406 1407 1408 1409 1410 1411
	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,
1412
						  bh_blocknr(right_buffer),
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
						  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,
1433
						  bh_blocknr(right_buffer),
1434
						  path->slots[1], 1);
1435 1436 1437 1438 1439
				if (wret)
					ret = wret;
				btrfs_block_release(root, path->nodes[0]);
				path->nodes[0] = right_buffer;
				path->slots[0] = 0;
1440 1441 1442 1443 1444 1445
				if (path->slots[1] == 0) {
					wret = fixup_low_keys(trans, root,
					           path, &disk_key, 1);
					if (wret)
						ret = wret;
				}
1446 1447 1448 1449 1450 1451 1452
				return ret;
			}
			mid = slot;
			double_split = 1;
		}
	}
	btrfs_set_header_nritems(&right->header, nritems - mid);
C
Chris Mason 已提交
1453 1454
	data_copy_size = btrfs_item_end(l->items + mid) -
			 leaf_data_end(root, l);
C
Chris Mason 已提交
1455 1456 1457 1458 1459 1460
	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 已提交
1461 1462
	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
		      btrfs_item_end(l->items + mid);
C
Chris Mason 已提交
1463

C
Chris Mason 已提交
1464
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1465
		u32 ioff = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1466 1467
		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
	}
C
Chris Mason 已提交
1468

1469
	btrfs_set_header_nritems(&l->header, mid);
C
Chris Mason 已提交
1470
	ret = 0;
1471
	wret = insert_ptr(trans, root, path, &right->items[0].key,
1472
			  bh_blocknr(right_buffer), path->slots[1] + 1, 1);
C
Chris Mason 已提交
1473 1474
	if (wret)
		ret = wret;
C
Chris Mason 已提交
1475 1476
	btrfs_mark_buffer_dirty(right_buffer);
	btrfs_mark_buffer_dirty(l_buf);
1477
	BUG_ON(path->slots[0] != slot);
1478
	if (mid <= slot) {
C
Chris Mason 已提交
1479
		btrfs_block_release(root, path->nodes[0]);
1480
		path->nodes[0] = right_buffer;
1481 1482
		path->slots[0] -= mid;
		path->slots[1] += 1;
1483
	} else
C
Chris Mason 已提交
1484
		btrfs_block_release(root, right_buffer);
1485
	BUG_ON(path->slots[0] < 0);
1486
	check_node(root, path, 1);
1487 1488 1489

	if (!double_split)
		return ret;
1490
	right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
1491 1492 1493
	if (IS_ERR(right_buffer))
		return PTR_ERR(right_buffer);

1494 1495
	right = btrfs_buffer_leaf(right_buffer);
	memset(&right->header, 0, sizeof(right->header));
1496
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1497
	btrfs_set_header_generation(&right->header, trans->transid);
1498
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1499
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1500 1501
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1502 1503 1504 1505
	btrfs_cpu_key_to_disk(&disk_key, ins_key);
	btrfs_set_header_nritems(&right->header, 0);
	wret = insert_ptr(trans, root, path,
			  &disk_key,
1506
			  bh_blocknr(right_buffer),
1507 1508 1509
			  path->slots[1], 1);
	if (wret)
		ret = wret;
1510 1511 1512 1513 1514
	if (path->slots[1] == 0) {
		wret = fixup_low_keys(trans, root, path, &disk_key, 1);
		if (wret)
			ret = wret;
	}
1515 1516 1517 1518 1519
	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);
1520 1521 1522
	return ret;
}

C
Chris Mason 已提交
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
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;
}

1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
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 已提交
1633 1634 1635 1636
/*
 * 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.
 */
1637 1638 1639
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)
1640
{
C
Chris Mason 已提交
1641
	int ret = 0;
1642
	int slot;
1643
	int slot_orig;
C
Chris Mason 已提交
1644
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1645
	struct buffer_head *leaf_buf;
1646
	u32 nritems;
1647
	unsigned int data_end;
C
Chris Mason 已提交
1648 1649 1650
	struct btrfs_disk_key disk_key;

	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1651

C
Chris Mason 已提交
1652
	/* create a root if there isn't one */
C
Chris Mason 已提交
1653
	if (!root->node)
C
Chris Mason 已提交
1654
		BUG();
1655
	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1656
	if (ret == 0) {
1657
		return -EEXIST;
C
Chris Mason 已提交
1658
	}
1659 1660
	if (ret < 0)
		goto out;
1661

1662 1663
	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1664
	leaf = btrfs_buffer_leaf(leaf_buf);
C
Chris Mason 已提交
1665

1666
	nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
1667
	data_end = leaf_data_end(root, leaf);
1668

C
Chris Mason 已提交
1669
	if (btrfs_leaf_free_space(root, leaf) <
1670
	    sizeof(struct btrfs_item) + data_size) {
1671
		BUG();
1672
	}
1673
	slot = path->slots[0];
1674
	BUG_ON(slot < 0);
1675 1676
	if (slot != nritems) {
		int i;
C
Chris Mason 已提交
1677
		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1678 1679 1680 1681 1682

		/*
		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
		 */
		/* first correct the data pointers */
C
Chris Mason 已提交
1683
		for (i = slot; i < nritems; i++) {
C
Chris Mason 已提交
1684
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1685 1686 1687
			btrfs_set_item_offset(leaf->items + i,
					      ioff - data_size);
		}
1688 1689

		/* shift the items */
C
Chris Mason 已提交
1690 1691 1692
		btrfs_memmove(root, leaf, leaf->items + slot + 1,
			      leaf->items + slot,
			      (nritems - slot) * sizeof(struct btrfs_item));
1693 1694

		/* shift the data */
C
Chris Mason 已提交
1695 1696 1697
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end - data_size, btrfs_leaf_data(leaf) +
			      data_end, old_data - data_end);
1698 1699
		data_end = old_data;
	}
1700
	/* setup the item for the new data */
C
Chris Mason 已提交
1701 1702
	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1703 1704
	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
	btrfs_set_item_size(leaf->items + slot, data_size);
1705
	btrfs_set_header_nritems(&leaf->header, nritems + 1);
C
Chris Mason 已提交
1706
	btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1707 1708

	ret = 0;
1709
	if (slot == 0)
1710
		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
C
Chris Mason 已提交
1711

C
Chris Mason 已提交
1712
	if (btrfs_leaf_free_space(root, leaf) < 0)
1713
		BUG();
1714
	check_leaf(root, path, 0);
1715
out:
1716 1717 1718 1719 1720 1721 1722
	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.
 */
1723 1724 1725
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *cpu_key, void *data, u32
		      data_size)
1726 1727
{
	int ret = 0;
C
Chris Mason 已提交
1728
	struct btrfs_path *path;
1729 1730
	u8 *ptr;

C
Chris Mason 已提交
1731 1732 1733
	path = btrfs_alloc_path();
	BUG_ON(!path);
	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
1734
	if (!ret) {
C
Chris Mason 已提交
1735 1736 1737
		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 已提交
1738
			     ptr, data, data_size);
C
Chris Mason 已提交
1739
		btrfs_mark_buffer_dirty(path->nodes[0]);
1740
	}
C
Chris Mason 已提交
1741
	btrfs_free_path(path);
C
Chris Mason 已提交
1742
	return ret;
1743 1744
}

C
Chris Mason 已提交
1745
/*
C
Chris Mason 已提交
1746
 * delete the pointer from a given node.
C
Chris Mason 已提交
1747 1748 1749 1750 1751
 *
 * 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.
 */
1752 1753
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot)
1754
{
C
Chris Mason 已提交
1755
	struct btrfs_node *node;
C
Chris Mason 已提交
1756
	struct buffer_head *parent = path->nodes[level];
1757
	u32 nritems;
C
Chris Mason 已提交
1758
	int ret = 0;
1759
	int wret;
1760

C
Chris Mason 已提交
1761
	node = btrfs_buffer_node(parent);
1762
	nritems = btrfs_header_nritems(&node->header);
1763
	if (slot != nritems -1) {
C
Chris Mason 已提交
1764 1765 1766 1767
		btrfs_memmove(root, node, node->ptrs + slot,
			      node->ptrs + slot + 1,
			      sizeof(struct btrfs_key_ptr) *
			      (nritems - slot - 1));
1768
	}
1769 1770 1771
	nritems--;
	btrfs_set_header_nritems(&node->header, nritems);
	if (nritems == 0 && parent == root->node) {
C
Chris Mason 已提交
1772 1773
		struct btrfs_header *header = btrfs_buffer_header(root->node);
		BUG_ON(btrfs_header_level(header) != 1);
1774
		/* just turn the root into a leaf and break */
C
Chris Mason 已提交
1775
		btrfs_set_header_level(header, 0);
1776
	} else if (slot == 0) {
1777
		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
C
Chris Mason 已提交
1778
				      level + 1);
C
Chris Mason 已提交
1779 1780
		if (wret)
			ret = wret;
1781
	}
C
Chris Mason 已提交
1782
	btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
1783
	return ret;
1784 1785
}

C
Chris Mason 已提交
1786 1787 1788 1789
/*
 * delete the item at the leaf level in path.  If that empties
 * the leaf, remove it from the tree
 */
1790 1791
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path)
1792 1793
{
	int slot;
C
Chris Mason 已提交
1794
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1795
	struct buffer_head *leaf_buf;
1796 1797
	int doff;
	int dsize;
C
Chris Mason 已提交
1798 1799
	int ret = 0;
	int wret;
1800
	u32 nritems;
1801

1802
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1803
	leaf = btrfs_buffer_leaf(leaf_buf);
1804
	slot = path->slots[0];
C
Chris Mason 已提交
1805 1806
	doff = btrfs_item_offset(leaf->items + slot);
	dsize = btrfs_item_size(leaf->items + slot);
1807
	nritems = btrfs_header_nritems(&leaf->header);
1808

1809
	if (slot != nritems - 1) {
1810
		int i;
C
Chris Mason 已提交
1811
		int data_end = leaf_data_end(root, leaf);
C
Chris Mason 已提交
1812 1813 1814 1815
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end + dsize,
			      btrfs_leaf_data(leaf) + data_end,
			      doff - data_end);
C
Chris Mason 已提交
1816
		for (i = slot + 1; i < nritems; i++) {
C
Chris Mason 已提交
1817
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1818 1819
			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
		}
C
Chris Mason 已提交
1820 1821 1822 1823
		btrfs_memmove(root, leaf, leaf->items + slot,
			      leaf->items + slot + 1,
			      sizeof(struct btrfs_item) *
			      (nritems - slot - 1));
1824
	}
1825 1826
	btrfs_set_header_nritems(&leaf->header, nritems - 1);
	nritems--;
C
Chris Mason 已提交
1827
	/* delete the leaf if we've emptied it */
1828
	if (nritems == 0) {
1829
		if (leaf_buf == root->node) {
1830
			btrfs_set_header_level(&leaf->header, 0);
1831
		} else {
1832
			clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1833
			wait_on_buffer(leaf_buf);
1834
			wret = del_ptr(trans, root, path, 1, path->slots[1]);
C
Chris Mason 已提交
1835 1836
			if (wret)
				ret = wret;
1837
			wret = btrfs_free_extent(trans, root,
1838
						 bh_blocknr(leaf_buf), 1, 1);
C
Chris Mason 已提交
1839 1840
			if (wret)
				ret = wret;
1841
		}
1842
	} else {
1843
		int used = leaf_space_used(leaf, 0, nritems);
C
Chris Mason 已提交
1844
		if (slot == 0) {
1845 1846
			wret = fixup_low_keys(trans, root, path,
					      &leaf->items[0].key, 1);
C
Chris Mason 已提交
1847 1848 1849 1850
			if (wret)
				ret = wret;
		}

C
Chris Mason 已提交
1851
		/* delete the leaf if it is mostly empty */
C
Chris Mason 已提交
1852
		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1853 1854 1855 1856
			/* push_leaf_left fixes the path.
			 * make sure the path still points to our leaf
			 * for possible call to del_ptr below
			 */
1857
			slot = path->slots[1];
C
Chris Mason 已提交
1858
			get_bh(leaf_buf);
1859
			wret = push_leaf_left(trans, root, path, 1);
1860
			if (wret < 0 && wret != -ENOSPC)
C
Chris Mason 已提交
1861
				ret = wret;
1862
			if (path->nodes[0] == leaf_buf &&
1863
			    btrfs_header_nritems(&leaf->header)) {
1864
				wret = push_leaf_right(trans, root, path, 1);
1865
				if (wret < 0 && wret != -ENOSPC)
C
Chris Mason 已提交
1866 1867
					ret = wret;
			}
1868
			if (btrfs_header_nritems(&leaf->header) == 0) {
1869
				u64 blocknr = bh_blocknr(leaf_buf);
1870
				clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1871
				wait_on_buffer(leaf_buf);
1872
				wret = del_ptr(trans, root, path, 1, slot);
C
Chris Mason 已提交
1873 1874
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1875
				btrfs_block_release(root, leaf_buf);
1876 1877
				wret = btrfs_free_extent(trans, root, blocknr,
							 1, 1);
C
Chris Mason 已提交
1878 1879
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1880
			} else {
C
Chris Mason 已提交
1881
				btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1882
				btrfs_block_release(root, leaf_buf);
1883
			}
1884
		} else {
C
Chris Mason 已提交
1885
			btrfs_mark_buffer_dirty(leaf_buf);
1886 1887
		}
	}
C
Chris Mason 已提交
1888
	return ret;
1889 1890
}

C
Chris Mason 已提交
1891 1892
/*
 * walk up the tree as far as required to find the next leaf.
C
Chris Mason 已提交
1893 1894
 * returns 0 if it found something or 1 if there are no greater leaves.
 * returns < 0 on io errors.
C
Chris Mason 已提交
1895
 */
C
Chris Mason 已提交
1896
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1897 1898 1899 1900
{
	int slot;
	int level = 1;
	u64 blocknr;
C
Chris Mason 已提交
1901 1902 1903
	struct buffer_head *c;
	struct btrfs_node *c_node;
	struct buffer_head *next = NULL;
1904

C
Chris Mason 已提交
1905
	while(level < BTRFS_MAX_LEVEL) {
1906
		if (!path->nodes[level])
C
Chris Mason 已提交
1907
			return 1;
1908 1909
		slot = path->slots[level] + 1;
		c = path->nodes[level];
C
Chris Mason 已提交
1910 1911
		c_node = btrfs_buffer_node(c);
		if (slot >= btrfs_header_nritems(&c_node->header)) {
1912 1913 1914
			level++;
			continue;
		}
C
Chris Mason 已提交
1915
		blocknr = btrfs_node_blockptr(c_node, slot);
C
Chris Mason 已提交
1916
		if (next)
C
Chris Mason 已提交
1917
			btrfs_block_release(root, next);
1918 1919 1920 1921 1922 1923 1924
		next = read_tree_block(root, blocknr);
		break;
	}
	path->slots[level] = slot;
	while(1) {
		level--;
		c = path->nodes[level];
C
Chris Mason 已提交
1925
		btrfs_block_release(root, c);
1926 1927 1928 1929
		path->nodes[level] = next;
		path->slots[level] = 0;
		if (!level)
			break;
1930
		next = read_tree_block(root,
C
Chris Mason 已提交
1931
		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1932 1933 1934
	}
	return 0;
}