ctree.c 53.9 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
#include <linux/module.h>
20 21
#include "ctree.h"
#include "disk-io.h"
22
#include "transaction.h"
23

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

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

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

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

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

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

78 79
	if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
				    trans->transid) {
C
Chris Mason 已提交
80 81 82
		*cow_ret = buf;
		return 0;
	}
83
	cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr);
84 85
	if (IS_ERR(cow))
		return PTR_ERR(cow);
C
Chris Mason 已提交
86
	cow_node = btrfs_buffer_node(cow);
C
Chris Mason 已提交
87 88
	if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
		WARN_ON(1);
C
Chris Mason 已提交
89
	memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
90
	btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow));
91
	btrfs_set_header_generation(&cow_node->header, trans->transid);
92
	btrfs_set_header_owner(&cow_node->header, root->root_key.objectid);
93 94 95
	ret = btrfs_inc_ref(trans, root, buf);
	if (ret)
		return ret;
C
Chris Mason 已提交
96 97
	if (buf == root->node) {
		root->node = cow;
C
Chris Mason 已提交
98
		get_bh(cow);
C
Chris Mason 已提交
99
		if (buf != root->commit_root) {
100
			btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
101
		}
C
Chris Mason 已提交
102
		btrfs_block_release(root, buf);
C
Chris Mason 已提交
103
	} else {
C
Chris Mason 已提交
104
		btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
105
					bh_blocknr(cow));
C
Chris Mason 已提交
106
		btrfs_mark_buffer_dirty(parent);
107
		btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
C
Chris Mason 已提交
108
	}
C
Chris Mason 已提交
109
	btrfs_block_release(root, buf);
C
Chris Mason 已提交
110
	mark_buffer_dirty(cow);
C
Chris Mason 已提交
111
	*cow_ret = cow;
C
Chris Mason 已提交
112 113 114
	return 0;
}

C
Chris Mason 已提交
115 116 117 118 119
/*
 * 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 已提交
120 121
static inline unsigned int leaf_data_end(struct btrfs_root *root,
					 struct btrfs_leaf *leaf)
122
{
123
	u32 nr = btrfs_header_nritems(&leaf->header);
124
	if (nr == 0)
C
Chris Mason 已提交
125
		return BTRFS_LEAF_DATA_SIZE(root);
C
Chris Mason 已提交
126
	return btrfs_item_offset(leaf->items + nr - 1);
127 128
}

C
Chris Mason 已提交
129 130 131
/*
 * compare two keys in a memcmp fashion
 */
C
Chris Mason 已提交
132
static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
133
{
C
Chris Mason 已提交
134 135 136 137 138
	struct btrfs_key k1;

	btrfs_disk_key_to_cpu(&k1, disk);

	if (k1.objectid > k2->objectid)
139
		return 1;
C
Chris Mason 已提交
140
	if (k1.objectid < k2->objectid)
141
		return -1;
C
Chris Mason 已提交
142 143 144 145
	if (k1.flags > k2->flags)
		return 1;
	if (k1.flags < k2->flags)
		return -1;
146 147 148 149
	if (k1.offset > k2->offset)
		return 1;
	if (k1.offset < k2->offset)
		return -1;
150 151
	return 0;
}
C
Chris Mason 已提交
152

C
Chris Mason 已提交
153 154
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
155
{
C
Chris Mason 已提交
156
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
157
	struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
C
Chris Mason 已提交
158
	int parent_slot;
159 160
	int slot;
	struct btrfs_key cpukey;
161
	u32 nritems = btrfs_header_nritems(&node->header);
C
Chris Mason 已提交
162 163

	if (path->nodes[level + 1])
C
Chris Mason 已提交
164
		parent = btrfs_buffer_node(path->nodes[level + 1]);
C
Chris Mason 已提交
165
	parent_slot = path->slots[level + 1];
166
	slot = path->slots[level];
167 168
	BUG_ON(nritems == 0);
	if (parent) {
C
Chris Mason 已提交
169
		struct btrfs_disk_key *parent_key;
C
Chris Mason 已提交
170 171
		parent_key = &parent->ptrs[parent_slot].key;
		BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
C
Chris Mason 已提交
172
			      sizeof(struct btrfs_disk_key)));
173
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
174
		       btrfs_header_blocknr(&node->header));
C
Chris Mason 已提交
175
	}
C
Chris Mason 已提交
176
	BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
177 178 179 180 181 182 183
	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 已提交
184 185 186 187
	}
	return 0;
}

C
Chris Mason 已提交
188 189
static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
		      int level)
C
Chris Mason 已提交
190
{
C
Chris Mason 已提交
191
	struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
C
Chris Mason 已提交
192
	struct btrfs_node *parent = NULL;
C
Chris Mason 已提交
193
	int parent_slot;
194 195 196
	int slot = path->slots[0];
	struct btrfs_key cpukey;

197
	u32 nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
198 199

	if (path->nodes[level + 1])
C
Chris Mason 已提交
200
		parent = btrfs_buffer_node(path->nodes[level + 1]);
C
Chris Mason 已提交
201
	parent_slot = path->slots[level + 1];
C
Chris Mason 已提交
202
	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
203 204 205 206 207

	if (nritems == 0)
		return 0;

	if (parent) {
C
Chris Mason 已提交
208
		struct btrfs_disk_key *parent_key;
C
Chris Mason 已提交
209
		parent_key = &parent->ptrs[parent_slot].key;
C
Chris Mason 已提交
210
		BUG_ON(memcmp(parent_key, &leaf->items[0].key,
C
Chris Mason 已提交
211
		       sizeof(struct btrfs_disk_key)));
212
		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
213
		       btrfs_header_blocknr(&leaf->header));
C
Chris Mason 已提交
214
	}
215 216 217 218 219 220 221 222 223 224 225
	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 已提交
226
	}
227 228
	BUG_ON(btrfs_item_offset(leaf->items) +
	       btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root));
C
Chris Mason 已提交
229 230 231
	return 0;
}

C
Chris Mason 已提交
232 233
static int check_block(struct btrfs_root *root, struct btrfs_path *path,
			int level)
C
Chris Mason 已提交
234
{
C
Chris Mason 已提交
235 236 237 238
	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 已提交
239
	if (level == 0)
C
Chris Mason 已提交
240 241
		return check_leaf(root, path, level);
	return check_node(root, path, level);
C
Chris Mason 已提交
242 243
}

C
Chris Mason 已提交
244 245 246 247 248 249 250 251 252
/*
 * 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 已提交
253
static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
254 255 256 257 258 259
		       int max, int *slot)
{
	int low = 0;
	int high = max;
	int mid;
	int ret;
C
Chris Mason 已提交
260
	struct btrfs_disk_key *tmp;
261 262 263

	while(low < high) {
		mid = (low + high) / 2;
C
Chris Mason 已提交
264
		tmp = (struct btrfs_disk_key *)(p + mid * item_size);
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
		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 已提交
280 281 282 283
/*
 * simple bin_search frontend that does the right thing for
 * leaves vs nodes
 */
C
Chris Mason 已提交
284
static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
285
{
286
	if (btrfs_is_leaf(c)) {
C
Chris Mason 已提交
287
		struct btrfs_leaf *l = (struct btrfs_leaf *)c;
C
Chris Mason 已提交
288 289
		return generic_bin_search((void *)l->items,
					  sizeof(struct btrfs_item),
290 291
					  key, btrfs_header_nritems(&c->header),
					  slot);
292
	} else {
C
Chris Mason 已提交
293 294
		return generic_bin_search((void *)c->ptrs,
					  sizeof(struct btrfs_key_ptr),
295 296
					  key, btrfs_header_nritems(&c->header),
					  slot);
297 298 299 300
	}
	return -1;
}

C
Chris Mason 已提交
301 302
static struct buffer_head *read_node_slot(struct btrfs_root *root,
				   struct buffer_head *parent_buf,
303 304
				   int slot)
{
C
Chris Mason 已提交
305
	struct btrfs_node *node = btrfs_buffer_node(parent_buf);
306 307
	if (slot < 0)
		return NULL;
308
	if (slot >= btrfs_header_nritems(&node->header))
309
		return NULL;
310
	return read_tree_block(root, btrfs_node_blockptr(node, slot));
311 312
}

313 314
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
			 *root, struct btrfs_path *path, int level)
315
{
C
Chris Mason 已提交
316 317 318 319
	struct buffer_head *right_buf;
	struct buffer_head *mid_buf;
	struct buffer_head *left_buf;
	struct buffer_head *parent_buf = NULL;
C
Chris Mason 已提交
320 321 322 323
	struct btrfs_node *right = NULL;
	struct btrfs_node *mid;
	struct btrfs_node *left = NULL;
	struct btrfs_node *parent = NULL;
324 325 326 327
	int ret = 0;
	int wret;
	int pslot;
	int orig_slot = path->slots[level];
328
	int err_on_enospc = 0;
329
	u64 orig_ptr;
330 331 332 333 334

	if (level == 0)
		return 0;

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

C
Chris Mason 已提交
338
	if (level < BTRFS_MAX_LEVEL - 1)
339 340 341
		parent_buf = path->nodes[level + 1];
	pslot = path->slots[level + 1];

C
Chris Mason 已提交
342 343 344 345
	/*
	 * deal with the case where there is only one pointer in the root
	 * by promoting the node below to a root
	 */
346
	if (!parent_buf) {
C
Chris Mason 已提交
347
		struct buffer_head *child;
348
		u64 blocknr = bh_blocknr(mid_buf);
349

350
		if (btrfs_header_nritems(&mid->header) != 1)
351 352 353 354 355 356 357
			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 已提交
358 359
		clean_tree_block(trans, root, mid_buf);
		wait_on_buffer(mid_buf);
360
		/* once for the path */
C
Chris Mason 已提交
361
		btrfs_block_release(root, mid_buf);
362
		/* once for the root ptr */
C
Chris Mason 已提交
363
		btrfs_block_release(root, mid_buf);
364
		return btrfs_free_extent(trans, root, blocknr, 1, 1);
365
	}
C
Chris Mason 已提交
366
	parent = btrfs_buffer_node(parent_buf);
367

C
Chris Mason 已提交
368 369
	if (btrfs_header_nritems(&mid->header) >
	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
370 371
		return 0;

372 373 374
	if (btrfs_header_nritems(&mid->header) < 2)
		err_on_enospc = 1;

375 376
	left_buf = read_node_slot(root, parent_buf, pslot - 1);
	right_buf = read_node_slot(root, parent_buf, pslot + 1);
377 378

	/* first, try to make some room in the middle buffer */
379
	if (left_buf) {
380 381 382 383 384 385
		wret = btrfs_cow_block(trans, root, left_buf,
				       parent_buf, pslot - 1, &left_buf);
		if (wret) {
			ret = wret;
			goto enospc;
		}
C
Chris Mason 已提交
386
		left = btrfs_buffer_node(left_buf);
387
		orig_slot += btrfs_header_nritems(&left->header);
388
		wret = push_node_left(trans, root, left_buf, mid_buf);
389 390
		if (wret < 0)
			ret = wret;
391 392
		if (btrfs_header_nritems(&mid->header) < 2)
			err_on_enospc = 1;
393
	}
394 395 396 397

	/*
	 * then try to empty the right most buffer into the middle
	 */
398
	if (right_buf) {
399 400 401 402 403 404 405
		wret = btrfs_cow_block(trans, root, right_buf,
				       parent_buf, pslot + 1, &right_buf);
		if (wret) {
			ret = wret;
			goto enospc;
		}

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

472
	/* update the path */
473
	if (left_buf) {
474
		if (btrfs_header_nritems(&left->header) > orig_slot) {
C
Chris Mason 已提交
475
			get_bh(left_buf);
476 477 478 479
			path->nodes[level] = left_buf;
			path->slots[level + 1] -= 1;
			path->slots[level] = orig_slot;
			if (mid_buf)
C
Chris Mason 已提交
480
				btrfs_block_release(root, mid_buf);
481
		} else {
482
			orig_slot -= btrfs_header_nritems(&left->header);
483 484 485
			path->slots[level] = orig_slot;
		}
	}
486
	/* double check we haven't messed things up */
C
Chris Mason 已提交
487
	check_block(root, path, level);
C
Chris Mason 已提交
488 489 490
	if (orig_ptr !=
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
				path->slots[level]))
491
		BUG();
492
enospc:
493
	if (right_buf)
C
Chris Mason 已提交
494
		btrfs_block_release(root, right_buf);
495
	if (left_buf)
C
Chris Mason 已提交
496
		btrfs_block_release(root, left_buf);
497 498 499
	return ret;
}

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
/* 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 已提交
541 542 543
		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
544 545 546 547 548 549 550 551 552
			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 已提交
553
		}
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
		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 已提交
585
		u32 right_nr;
586
		right = btrfs_buffer_node(right_buf);
C
Chris Mason 已提交
587 588 589 590
		right_nr = btrfs_header_nritems(&right->header);
		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
591 592 593 594 595 596 597 598 599 600
			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 已提交
601
		}
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
		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 已提交
628 629 630 631 632 633
/*
 * 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 已提交
634 635
 * be inserted, and 1 is returned.  If there are other errors during the
 * search a negative error number is returned.
C
Chris Mason 已提交
636 637 638 639
 *
 * 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 已提交
640
 */
641 642 643
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)
644
{
C
Chris Mason 已提交
645 646
	struct buffer_head *b;
	struct buffer_head *cow_buf;
C
Chris Mason 已提交
647
	struct btrfs_node *c;
648 649 650
	int slot;
	int ret;
	int level;
C
Chris Mason 已提交
651

C
Chris Mason 已提交
652 653
	WARN_ON(p->nodes[0] != NULL);
	WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
654 655
again:
	b = root->node;
C
Chris Mason 已提交
656
	get_bh(b);
657
	while (b) {
C
Chris Mason 已提交
658 659
		c = btrfs_buffer_node(b);
		level = btrfs_header_level(&c->header);
C
Chris Mason 已提交
660 661
		if (cow) {
			int wret;
C
Chris Mason 已提交
662 663 664
			wret = btrfs_cow_block(trans, root, b,
					       p->nodes[level + 1],
					       p->slots[level + 1],
665
					       &cow_buf);
666 667 668 669
			if (wret) {
				btrfs_block_release(root, cow_buf);
				return wret;
			}
C
Chris Mason 已提交
670
			b = cow_buf;
C
Chris Mason 已提交
671
			c = btrfs_buffer_node(b);
C
Chris Mason 已提交
672 673
		}
		BUG_ON(!cow && ins_len);
C
Chris Mason 已提交
674 675 676
		if (level != btrfs_header_level(&c->header))
			WARN_ON(1);
		level = btrfs_header_level(&c->header);
677
		p->nodes[level] = b;
C
Chris Mason 已提交
678
		ret = check_block(root, p, level);
C
Chris Mason 已提交
679 680
		if (ret)
			return -1;
681
		ret = bin_search(c, key, &slot);
682
		if (!btrfs_is_leaf(c)) {
683 684 685
			if (ret && slot > 0)
				slot -= 1;
			p->slots[level] = slot;
686 687
			if (ins_len > 0 && btrfs_header_nritems(&c->header) >=
			    BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
688
				int sret = split_node(trans, root, p, level);
C
Chris Mason 已提交
689 690 691 692
				BUG_ON(sret > 0);
				if (sret)
					return sret;
				b = p->nodes[level];
C
Chris Mason 已提交
693
				c = btrfs_buffer_node(b);
C
Chris Mason 已提交
694
				slot = p->slots[level];
695
			} else if (ins_len < 0) {
696 697
				int sret = balance_level(trans, root, p,
							 level);
698 699 700 701 702
				if (sret)
					return sret;
				b = p->nodes[level];
				if (!b)
					goto again;
C
Chris Mason 已提交
703
				c = btrfs_buffer_node(b);
704
				slot = p->slots[level];
705
				BUG_ON(btrfs_header_nritems(&c->header) == 1);
C
Chris Mason 已提交
706
			}
707
			b = read_tree_block(root, btrfs_node_blockptr(c, slot));
708
		} else {
C
Chris Mason 已提交
709
			struct btrfs_leaf *l = (struct btrfs_leaf *)c;
710
			p->slots[level] = slot;
C
Chris Mason 已提交
711
			if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
C
Chris Mason 已提交
712
			    sizeof(struct btrfs_item) + ins_len) {
713 714
				int sret = split_leaf(trans, root, key,
						      p, ins_len);
C
Chris Mason 已提交
715 716 717 718
				BUG_ON(sret > 0);
				if (sret)
					return sret;
			}
719 720 721
			return ret;
		}
	}
C
Chris Mason 已提交
722
	return 1;
723 724
}

C
Chris Mason 已提交
725 726 727 728 729 730
/*
 * 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 已提交
731 732 733
 *
 * 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 已提交
734
 */
735 736 737
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)
738 739
{
	int i;
C
Chris Mason 已提交
740
	int ret = 0;
C
Chris Mason 已提交
741 742
	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
		struct btrfs_node *t;
743
		int tslot = path->slots[i];
744
		if (!path->nodes[i])
745
			break;
C
Chris Mason 已提交
746
		t = btrfs_buffer_node(path->nodes[i]);
C
Chris Mason 已提交
747 748
		btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
		btrfs_mark_buffer_dirty(path->nodes[i]);
749 750 751
		if (tslot != 0)
			break;
	}
C
Chris Mason 已提交
752
	return ret;
753 754
}

C
Chris Mason 已提交
755 756
/*
 * try to push data from one node into the next node left in the
757
 * tree.
C
Chris Mason 已提交
758 759 760
 *
 * 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 已提交
761
 */
762
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
763 764
			  *root, struct buffer_head *dst_buf, struct
			  buffer_head *src_buf)
765
{
C
Chris Mason 已提交
766 767
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
768
	int push_items = 0;
769 770
	int src_nritems;
	int dst_nritems;
C
Chris Mason 已提交
771
	int ret = 0;
772

773 774
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
775
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
776

777
	if (push_items <= 0) {
778
		return 1;
779
	}
780

781
	if (src_nritems < push_items)
782 783
		push_items = src_nritems;

C
Chris Mason 已提交
784 785
	btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
		     push_items * sizeof(struct btrfs_key_ptr));
786
	if (push_items < src_nritems) {
C
Chris Mason 已提交
787
		btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
C
Chris Mason 已提交
788
			(src_nritems - push_items) *
C
Chris Mason 已提交
789
			sizeof(struct btrfs_key_ptr));
790
	}
791 792
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
C
Chris Mason 已提交
793 794
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
795 796 797 798 799 800 801 802 803 804 805 806
	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
 */
807
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
808 809
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf)
810
{
C
Chris Mason 已提交
811 812
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
813 814 815 816 817 818
	int push_items = 0;
	int max_push;
	int src_nritems;
	int dst_nritems;
	int ret = 0;

819 820
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
821
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
822 823 824 825 826 827 828 829 830 831 832
	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 已提交
833 834 835 836 837 838
	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));
839

840 841
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
842

C
Chris Mason 已提交
843 844
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
C
Chris Mason 已提交
845
	return ret;
846 847
}

C
Chris Mason 已提交
848 849 850 851
/*
 * 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 已提交
852 853
 *
 * returns zero on success or < 0 on failure.
C
Chris Mason 已提交
854
 */
855 856
static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int level)
C
Chris Mason 已提交
857
{
C
Chris Mason 已提交
858
	struct buffer_head *t;
C
Chris Mason 已提交
859 860
	struct btrfs_node *lower;
	struct btrfs_node *c;
C
Chris Mason 已提交
861
	struct btrfs_disk_key *lower_key;
C
Chris Mason 已提交
862 863 864 865

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

866
	t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr);
867 868
	if (IS_ERR(t))
		return PTR_ERR(t);
C
Chris Mason 已提交
869
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
870
	memset(c, 0, root->blocksize);
871 872
	btrfs_set_header_nritems(&c->header, 1);
	btrfs_set_header_level(&c->header, level);
873
	btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
874
	btrfs_set_header_generation(&c->header, trans->transid);
875
	btrfs_set_header_owner(&c->header, root->root_key.objectid);
C
Chris Mason 已提交
876
	lower = btrfs_buffer_node(path->nodes[level-1]);
C
Chris Mason 已提交
877 878
	memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(c->header.fsid));
879
	if (btrfs_is_leaf(lower))
C
Chris Mason 已提交
880
		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
C
Chris Mason 已提交
881
	else
C
Chris Mason 已提交
882
		lower_key = &lower->ptrs[0].key;
C
Chris Mason 已提交
883 884
	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
		     sizeof(struct btrfs_disk_key));
885
	btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
886

C
Chris Mason 已提交
887
	btrfs_mark_buffer_dirty(t);
888

C
Chris Mason 已提交
889
	/* the super has an extra ref to root->node */
C
Chris Mason 已提交
890
	btrfs_block_release(root, root->node);
C
Chris Mason 已提交
891
	root->node = t;
C
Chris Mason 已提交
892
	get_bh(t);
C
Chris Mason 已提交
893 894 895 896 897
	path->nodes[level] = t;
	path->slots[level] = 0;
	return 0;
}

C
Chris Mason 已提交
898 899 900
/*
 * worker function to insert a single pointer in a node.
 * the node should have enough room for the pointer already
C
Chris Mason 已提交
901
 *
C
Chris Mason 已提交
902 903
 * slot and level indicate where you want the key to go, and
 * blocknr is the block the key points to.
C
Chris Mason 已提交
904 905
 *
 * returns zero on success and < 0 on any error
C
Chris Mason 已提交
906
 */
907 908 909
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 已提交
910
{
C
Chris Mason 已提交
911
	struct btrfs_node *lower;
C
Chris Mason 已提交
912
	int nritems;
C
Chris Mason 已提交
913 914

	BUG_ON(!path->nodes[level]);
C
Chris Mason 已提交
915
	lower = btrfs_buffer_node(path->nodes[level]);
916
	nritems = btrfs_header_nritems(&lower->header);
C
Chris Mason 已提交
917 918
	if (slot > nritems)
		BUG();
C
Chris Mason 已提交
919
	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
C
Chris Mason 已提交
920 921
		BUG();
	if (slot != nritems) {
C
Chris Mason 已提交
922 923 924
		btrfs_memmove(root, lower, lower->ptrs + slot + 1,
			      lower->ptrs + slot,
			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
C
Chris Mason 已提交
925
	}
C
Chris Mason 已提交
926 927
	btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
		     key, sizeof(struct btrfs_disk_key));
928
	btrfs_set_node_blockptr(lower, slot, blocknr);
929
	btrfs_set_header_nritems(&lower->header, nritems + 1);
C
Chris Mason 已提交
930
	btrfs_mark_buffer_dirty(path->nodes[level]);
931
	check_node(root, path, level);
C
Chris Mason 已提交
932 933 934
	return 0;
}

C
Chris Mason 已提交
935 936 937 938 939 940
/*
 * 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 已提交
941 942
 *
 * returns 0 on success and < 0 on failure
C
Chris Mason 已提交
943
 */
944 945
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, int level)
946
{
C
Chris Mason 已提交
947
	struct buffer_head *t;
C
Chris Mason 已提交
948
	struct btrfs_node *c;
C
Chris Mason 已提交
949
	struct buffer_head *split_buffer;
C
Chris Mason 已提交
950
	struct btrfs_node *split;
951
	int mid;
C
Chris Mason 已提交
952
	int ret;
C
Chris Mason 已提交
953
	int wret;
954
	u32 c_nritems;
955

C
Chris Mason 已提交
956
	t = path->nodes[level];
C
Chris Mason 已提交
957
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
958 959
	if (t == root->node) {
		/* trying to split the root, lets make a new one */
960
		ret = insert_new_root(trans, root, path, level + 1);
C
Chris Mason 已提交
961 962
		if (ret)
			return ret;
963 964 965 966 967 968 969 970
	} 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;
971 972
		if (ret < 0)
			return ret;
973
	}
974

975
	c_nritems = btrfs_header_nritems(&c->header);
976
	split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr);
977 978 979
	if (IS_ERR(split_buffer))
		return PTR_ERR(split_buffer);

C
Chris Mason 已提交
980
	split = btrfs_buffer_node(split_buffer);
981
	btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
982
	btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
983
	btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer));
984
	btrfs_set_header_generation(&split->header, trans->transid);
985
	btrfs_set_header_owner(&split->header, root->root_key.objectid);
C
Chris Mason 已提交
986 987
	memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(split->header.fsid));
988
	mid = (c_nritems + 1) / 2;
C
Chris Mason 已提交
989 990
	btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
		     (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
991 992
	btrfs_set_header_nritems(&split->header, c_nritems - mid);
	btrfs_set_header_nritems(&c->header, mid);
C
Chris Mason 已提交
993 994
	ret = 0;

C
Chris Mason 已提交
995 996
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(split_buffer);
997
	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
998
			  bh_blocknr(split_buffer), path->slots[level + 1] + 1,
C
Chris Mason 已提交
999
			  level + 1);
C
Chris Mason 已提交
1000 1001 1002
	if (wret)
		ret = wret;

C
Chris Mason 已提交
1003
	if (path->slots[level] >= mid) {
C
Chris Mason 已提交
1004
		path->slots[level] -= mid;
C
Chris Mason 已提交
1005
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1006 1007 1008
		path->nodes[level] = split_buffer;
		path->slots[level + 1] += 1;
	} else {
C
Chris Mason 已提交
1009
		btrfs_block_release(root, split_buffer);
1010
	}
C
Chris Mason 已提交
1011
	return ret;
1012 1013
}

C
Chris Mason 已提交
1014 1015 1016 1017 1018
/*
 * 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 已提交
1019
static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
1020 1021
{
	int data_len;
1022 1023
	int nritems = btrfs_header_nritems(&l->header);
	int end = min(nritems, start + nr) - 1;
1024 1025 1026

	if (!nr)
		return 0;
C
Chris Mason 已提交
1027 1028 1029
	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;
1030
	WARN_ON(data_len < 0);
1031 1032 1033
	return data_len;
}

1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
/*
 * 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 已提交
1045 1046 1047
/*
 * 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 已提交
1048 1049 1050
 *
 * 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 已提交
1051
 */
1052 1053
static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int data_size)
C
Chris Mason 已提交
1054
{
C
Chris Mason 已提交
1055 1056
	struct buffer_head *left_buf = path->nodes[0];
	struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
C
Chris Mason 已提交
1057
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1058 1059 1060
	struct buffer_head *right_buf;
	struct buffer_head *upper;
	struct btrfs_node *upper_node;
C
Chris Mason 已提交
1061 1062 1063 1064 1065
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1066
	struct btrfs_item *item;
1067 1068
	u32 left_nritems;
	u32 right_nritems;
1069
	int ret;
C
Chris Mason 已提交
1070 1071 1072 1073 1074 1075

	slot = path->slots[1];
	if (!path->nodes[1]) {
		return 1;
	}
	upper = path->nodes[1];
C
Chris Mason 已提交
1076 1077
	upper_node = btrfs_buffer_node(upper);
	if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
C
Chris Mason 已提交
1078 1079
		return 1;
	}
C
Chris Mason 已提交
1080 1081 1082
	right_buf = read_tree_block(root,
		    btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1083
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1084
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1085
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1086 1087
		return 1;
	}
C
Chris Mason 已提交
1088
	/* cow and double check */
1089 1090 1091 1092 1093 1094
	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 已提交
1095
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1096
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1097
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1098
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1099 1100 1101
		return 1;
	}

1102
	left_nritems = btrfs_header_nritems(&left->header);
1103 1104 1105 1106 1107
	if (left_nritems == 0) {
		btrfs_block_release(root, right_buf);
		return 1;
	}
	for (i = left_nritems - 1; i >= 1; i--) {
C
Chris Mason 已提交
1108 1109 1110
		item = left->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1111 1112
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
C
Chris Mason 已提交
1113 1114
			break;
		push_items++;
C
Chris Mason 已提交
1115
		push_space += btrfs_item_size(item) + sizeof(*item);
C
Chris Mason 已提交
1116 1117
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1118
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1119 1120
		return 1;
	}
1121 1122
	if (push_items == left_nritems)
		WARN_ON(1);
1123
	right_nritems = btrfs_header_nritems(&right->header);
C
Chris Mason 已提交
1124
	/* push left to right */
C
Chris Mason 已提交
1125
	push_space = btrfs_item_end(left->items + left_nritems - push_items);
C
Chris Mason 已提交
1126
	push_space -= leaf_data_end(root, left);
C
Chris Mason 已提交
1127
	/* make room in the right data area */
C
Chris Mason 已提交
1128 1129 1130 1131 1132
	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 已提交
1133
	/* copy from the left data area */
C
Chris Mason 已提交
1134 1135 1136 1137 1138
	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 已提交
1139
		right_nritems * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1140
	/* copy the items from left to right */
C
Chris Mason 已提交
1141 1142 1143
	btrfs_memcpy(root, right, right->items, left->items +
		     left_nritems - push_items,
		     push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1144 1145

	/* update the item pointers */
1146 1147
	right_nritems += push_items;
	btrfs_set_header_nritems(&right->header, right_nritems);
C
Chris Mason 已提交
1148
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1149
	for (i = 0; i < right_nritems; i++) {
C
Chris Mason 已提交
1150 1151 1152
		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 已提交
1153
	}
1154 1155
	left_nritems -= push_items;
	btrfs_set_header_nritems(&left->header, left_nritems);
C
Chris Mason 已提交
1156

C
Chris Mason 已提交
1157 1158
	btrfs_mark_buffer_dirty(left_buf);
	btrfs_mark_buffer_dirty(right_buf);
1159

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

C
Chris Mason 已提交
1164
	/* then fixup the leaf pointer in the path */
1165 1166
	if (path->slots[0] >= left_nritems) {
		path->slots[0] -= left_nritems;
C
Chris Mason 已提交
1167
		btrfs_block_release(root, path->nodes[0]);
C
Chris Mason 已提交
1168 1169 1170
		path->nodes[0] = right_buf;
		path->slots[1] += 1;
	} else {
C
Chris Mason 已提交
1171
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1172
	}
1173 1174
	if (path->nodes[1])
		check_node(root, path, 1);
C
Chris Mason 已提交
1175 1176
	return 0;
}
C
Chris Mason 已提交
1177 1178 1179 1180
/*
 * 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
 */
1181 1182
static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int data_size)
1183
{
C
Chris Mason 已提交
1184 1185 1186
	struct buffer_head *right_buf = path->nodes[0];
	struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
	struct buffer_head *t;
C
Chris Mason 已提交
1187
	struct btrfs_leaf *left;
1188 1189 1190 1191 1192
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1193
	struct btrfs_item *item;
1194
	u32 old_left_nritems;
C
Chris Mason 已提交
1195 1196
	int ret = 0;
	int wret;
1197 1198 1199 1200 1201 1202 1203 1204

	slot = path->slots[1];
	if (slot == 0) {
		return 1;
	}
	if (!path->nodes[1]) {
		return 1;
	}
C
Chris Mason 已提交
1205 1206 1207
	t = read_tree_block(root,
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1208
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1209
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1210
		btrfs_block_release(root, t);
1211 1212
		return 1;
	}
C
Chris Mason 已提交
1213 1214

	/* cow and double check */
1215 1216 1217 1218 1219
	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 已提交
1220
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1221
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1222
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1223
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1224 1225 1226
		return 1;
	}

1227 1228 1229 1230 1231 1232
	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++) {
1233 1234 1235
		item = right->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1236 1237
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
1238 1239
			break;
		push_items++;
C
Chris Mason 已提交
1240
		push_space += btrfs_item_size(item) + sizeof(*item);
1241 1242
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1243
		btrfs_block_release(root, t);
1244 1245
		return 1;
	}
1246 1247
	if (push_items == btrfs_header_nritems(&right->header))
		WARN_ON(1);
1248
	/* push data from right to left */
C
Chris Mason 已提交
1249 1250 1251
	btrfs_memcpy(root, left, left->items +
		     btrfs_header_nritems(&left->header),
		     right->items, push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1252
	push_space = BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1253
		     btrfs_item_offset(right->items + push_items -1);
C
Chris Mason 已提交
1254 1255 1256 1257 1258
	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);
1259
	old_left_nritems = btrfs_header_nritems(&left->header);
1260 1261
	BUG_ON(old_left_nritems < 0);

C
Chris Mason 已提交
1262
	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
C
Chris Mason 已提交
1263 1264 1265
		u32 ioff = btrfs_item_offset(left->items + i);
		btrfs_set_item_offset(left->items + i, ioff -
				     (BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1266 1267
				      btrfs_item_offset(left->items +
						        old_left_nritems - 1)));
1268
	}
1269
	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1270 1271

	/* fixup right node */
C
Chris Mason 已提交
1272
	push_space = btrfs_item_offset(right->items + push_items - 1) -
C
Chris Mason 已提交
1273
		     leaf_data_end(root, right);
C
Chris Mason 已提交
1274 1275 1276 1277 1278
	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,
1279
		(btrfs_header_nritems(&right->header) - push_items) *
C
Chris Mason 已提交
1280
		sizeof(struct btrfs_item));
1281 1282 1283
	btrfs_set_header_nritems(&right->header,
				 btrfs_header_nritems(&right->header) -
				 push_items);
C
Chris Mason 已提交
1284
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1285

1286
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1287 1288 1289
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
1290
	}
1291

C
Chris Mason 已提交
1292 1293
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);
1294

1295
	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
C
Chris Mason 已提交
1296 1297
	if (wret)
		ret = wret;
1298 1299 1300 1301

	/* then fixup the leaf pointer in the path */
	if (path->slots[0] < push_items) {
		path->slots[0] += old_left_nritems;
C
Chris Mason 已提交
1302
		btrfs_block_release(root, path->nodes[0]);
1303
		path->nodes[0] = t;
1304 1305
		path->slots[1] -= 1;
	} else {
C
Chris Mason 已提交
1306
		btrfs_block_release(root, t);
1307 1308
		path->slots[0] -= push_items;
	}
1309
	BUG_ON(path->slots[0] < 0);
1310 1311
	if (path->nodes[1])
		check_node(root, path, 1);
C
Chris Mason 已提交
1312
	return ret;
1313 1314
}

C
Chris Mason 已提交
1315 1316 1317
/*
 * 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 已提交
1318 1319
 *
 * returns 0 if all went well and < 0 on failure.
C
Chris Mason 已提交
1320
 */
1321
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1322 1323
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size)
1324
{
C
Chris Mason 已提交
1325
	struct buffer_head *l_buf;
C
Chris Mason 已提交
1326
	struct btrfs_leaf *l;
1327
	u32 nritems;
1328 1329
	int mid;
	int slot;
C
Chris Mason 已提交
1330
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1331
	struct buffer_head *right_buffer;
C
Chris Mason 已提交
1332
	int space_needed = data_size + sizeof(struct btrfs_item);
1333 1334 1335
	int data_copy_size;
	int rt_data_off;
	int i;
1336
	int ret = 0;
C
Chris Mason 已提交
1337
	int wret;
1338 1339
	int double_split = 0;
	struct btrfs_disk_key disk_key;
C
Chris Mason 已提交
1340

C
Chris Mason 已提交
1341
	/* first try to make some room by pushing left and right */
1342
	wret = push_leaf_left(trans, root, path, data_size);
C
Chris Mason 已提交
1343 1344 1345
	if (wret < 0)
		return wret;
	if (wret) {
1346
		wret = push_leaf_right(trans, root, path, data_size);
C
Chris Mason 已提交
1347 1348 1349
		if (wret < 0)
			return wret;
	}
C
Chris Mason 已提交
1350
	l_buf = path->nodes[0];
C
Chris Mason 已提交
1351
	l = btrfs_buffer_leaf(l_buf);
C
Chris Mason 已提交
1352 1353

	/* did the pushes work? */
C
Chris Mason 已提交
1354 1355
	if (btrfs_leaf_free_space(root, l) >=
	    sizeof(struct btrfs_item) + data_size)
C
Chris Mason 已提交
1356 1357
		return 0;

C
Chris Mason 已提交
1358
	if (!path->nodes[1]) {
1359
		ret = insert_new_root(trans, root, path, 1);
C
Chris Mason 已提交
1360 1361 1362
		if (ret)
			return ret;
	}
1363
	slot = path->slots[0];
1364
	nritems = btrfs_header_nritems(&l->header);
1365
	mid = (nritems + 1)/ 2;
1366

1367
	right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
1368 1369 1370
	if (IS_ERR(right_buffer))
		return PTR_ERR(right_buffer);

C
Chris Mason 已提交
1371
	right = btrfs_buffer_leaf(right_buffer);
C
Chris Mason 已提交
1372
	memset(&right->header, 0, sizeof(right->header));
1373
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1374
	btrfs_set_header_generation(&right->header, trans->transid);
1375
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1376
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1377 1378
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1379 1380 1381 1382 1383 1384 1385 1386 1387
	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,
1388
						  bh_blocknr(right_buffer),
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
						  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,
1409
						  bh_blocknr(right_buffer),
1410
						  path->slots[1], 1);
1411 1412 1413 1414 1415
				if (wret)
					ret = wret;
				btrfs_block_release(root, path->nodes[0]);
				path->nodes[0] = right_buffer;
				path->slots[0] = 0;
1416 1417 1418 1419 1420 1421
				if (path->slots[1] == 0) {
					wret = fixup_low_keys(trans, root,
					           path, &disk_key, 1);
					if (wret)
						ret = wret;
				}
1422 1423 1424 1425 1426 1427 1428
				return ret;
			}
			mid = slot;
			double_split = 1;
		}
	}
	btrfs_set_header_nritems(&right->header, nritems - mid);
C
Chris Mason 已提交
1429 1430
	data_copy_size = btrfs_item_end(l->items + mid) -
			 leaf_data_end(root, l);
C
Chris Mason 已提交
1431 1432 1433 1434 1435 1436
	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 已提交
1437 1438
	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
		      btrfs_item_end(l->items + mid);
C
Chris Mason 已提交
1439

C
Chris Mason 已提交
1440
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1441
		u32 ioff = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1442 1443
		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
	}
C
Chris Mason 已提交
1444

1445
	btrfs_set_header_nritems(&l->header, mid);
C
Chris Mason 已提交
1446
	ret = 0;
1447
	wret = insert_ptr(trans, root, path, &right->items[0].key,
1448
			  bh_blocknr(right_buffer), path->slots[1] + 1, 1);
C
Chris Mason 已提交
1449 1450
	if (wret)
		ret = wret;
C
Chris Mason 已提交
1451 1452
	btrfs_mark_buffer_dirty(right_buffer);
	btrfs_mark_buffer_dirty(l_buf);
1453
	BUG_ON(path->slots[0] != slot);
1454
	if (mid <= slot) {
C
Chris Mason 已提交
1455
		btrfs_block_release(root, path->nodes[0]);
1456
		path->nodes[0] = right_buffer;
1457 1458
		path->slots[0] -= mid;
		path->slots[1] += 1;
1459
	} else
C
Chris Mason 已提交
1460
		btrfs_block_release(root, right_buffer);
1461
	BUG_ON(path->slots[0] < 0);
1462
	check_node(root, path, 1);
1463 1464 1465

	if (!double_split)
		return ret;
1466
	right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
1467 1468 1469
	if (IS_ERR(right_buffer))
		return PTR_ERR(right_buffer);

1470 1471
	right = btrfs_buffer_leaf(right_buffer);
	memset(&right->header, 0, sizeof(right->header));
1472
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1473
	btrfs_set_header_generation(&right->header, trans->transid);
1474
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1475
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1476 1477
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1478 1479 1480 1481
	btrfs_cpu_key_to_disk(&disk_key, ins_key);
	btrfs_set_header_nritems(&right->header, 0);
	wret = insert_ptr(trans, root, path,
			  &disk_key,
1482
			  bh_blocknr(right_buffer),
1483 1484 1485
			  path->slots[1], 1);
	if (wret)
		ret = wret;
1486 1487 1488 1489 1490
	if (path->slots[1] == 0) {
		wret = fixup_low_keys(trans, root, path, &disk_key, 1);
		if (wret)
			ret = wret;
	}
1491 1492 1493 1494 1495
	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);
1496 1497 1498
	return ret;
}

C
Chris Mason 已提交
1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554
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;
}

1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 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
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 已提交
1609 1610 1611 1612
/*
 * 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.
 */
1613 1614 1615
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)
1616
{
C
Chris Mason 已提交
1617
	int ret = 0;
1618
	int slot;
1619
	int slot_orig;
C
Chris Mason 已提交
1620
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1621
	struct buffer_head *leaf_buf;
1622
	u32 nritems;
1623
	unsigned int data_end;
C
Chris Mason 已提交
1624 1625 1626
	struct btrfs_disk_key disk_key;

	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1627

C
Chris Mason 已提交
1628
	/* create a root if there isn't one */
C
Chris Mason 已提交
1629
	if (!root->node)
C
Chris Mason 已提交
1630
		BUG();
1631
	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1632
	if (ret == 0) {
1633
		return -EEXIST;
C
Chris Mason 已提交
1634
	}
1635 1636
	if (ret < 0)
		goto out;
1637

1638 1639
	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1640
	leaf = btrfs_buffer_leaf(leaf_buf);
C
Chris Mason 已提交
1641

1642
	nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
1643
	data_end = leaf_data_end(root, leaf);
1644

C
Chris Mason 已提交
1645
	if (btrfs_leaf_free_space(root, leaf) <
1646
	    sizeof(struct btrfs_item) + data_size) {
1647
		BUG();
1648
	}
1649
	slot = path->slots[0];
1650
	BUG_ON(slot < 0);
1651 1652
	if (slot != nritems) {
		int i;
C
Chris Mason 已提交
1653
		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1654 1655 1656 1657 1658

		/*
		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
		 */
		/* first correct the data pointers */
C
Chris Mason 已提交
1659
		for (i = slot; i < nritems; i++) {
C
Chris Mason 已提交
1660
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1661 1662 1663
			btrfs_set_item_offset(leaf->items + i,
					      ioff - data_size);
		}
1664 1665

		/* shift the items */
C
Chris Mason 已提交
1666 1667 1668
		btrfs_memmove(root, leaf, leaf->items + slot + 1,
			      leaf->items + slot,
			      (nritems - slot) * sizeof(struct btrfs_item));
1669 1670

		/* shift the data */
C
Chris Mason 已提交
1671 1672 1673
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end - data_size, btrfs_leaf_data(leaf) +
			      data_end, old_data - data_end);
1674 1675
		data_end = old_data;
	}
1676
	/* setup the item for the new data */
C
Chris Mason 已提交
1677 1678
	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1679 1680
	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
	btrfs_set_item_size(leaf->items + slot, data_size);
1681
	btrfs_set_header_nritems(&leaf->header, nritems + 1);
C
Chris Mason 已提交
1682
	btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1683 1684

	ret = 0;
1685
	if (slot == 0)
1686
		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
C
Chris Mason 已提交
1687

C
Chris Mason 已提交
1688
	if (btrfs_leaf_free_space(root, leaf) < 0)
1689
		BUG();
1690
	check_leaf(root, path, 0);
1691
out:
1692 1693 1694 1695 1696 1697 1698
	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.
 */
1699 1700 1701
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *cpu_key, void *data, u32
		      data_size)
1702 1703
{
	int ret = 0;
C
Chris Mason 已提交
1704
	struct btrfs_path *path;
1705 1706
	u8 *ptr;

C
Chris Mason 已提交
1707 1708 1709
	path = btrfs_alloc_path();
	BUG_ON(!path);
	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
1710
	if (!ret) {
C
Chris Mason 已提交
1711 1712 1713
		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 已提交
1714
			     ptr, data, data_size);
C
Chris Mason 已提交
1715
		btrfs_mark_buffer_dirty(path->nodes[0]);
1716
	}
C
Chris Mason 已提交
1717
	btrfs_free_path(path);
C
Chris Mason 已提交
1718
	return ret;
1719 1720
}

C
Chris Mason 已提交
1721
/*
C
Chris Mason 已提交
1722
 * delete the pointer from a given node.
C
Chris Mason 已提交
1723 1724 1725 1726 1727
 *
 * 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.
 */
1728 1729
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot)
1730
{
C
Chris Mason 已提交
1731
	struct btrfs_node *node;
C
Chris Mason 已提交
1732
	struct buffer_head *parent = path->nodes[level];
1733
	u32 nritems;
C
Chris Mason 已提交
1734
	int ret = 0;
1735
	int wret;
1736

C
Chris Mason 已提交
1737
	node = btrfs_buffer_node(parent);
1738
	nritems = btrfs_header_nritems(&node->header);
1739
	if (slot != nritems -1) {
C
Chris Mason 已提交
1740 1741 1742 1743
		btrfs_memmove(root, node, node->ptrs + slot,
			      node->ptrs + slot + 1,
			      sizeof(struct btrfs_key_ptr) *
			      (nritems - slot - 1));
1744
	}
1745 1746 1747
	nritems--;
	btrfs_set_header_nritems(&node->header, nritems);
	if (nritems == 0 && parent == root->node) {
C
Chris Mason 已提交
1748 1749
		struct btrfs_header *header = btrfs_buffer_header(root->node);
		BUG_ON(btrfs_header_level(header) != 1);
1750
		/* just turn the root into a leaf and break */
C
Chris Mason 已提交
1751
		btrfs_set_header_level(header, 0);
1752
	} else if (slot == 0) {
1753
		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
C
Chris Mason 已提交
1754
				      level + 1);
C
Chris Mason 已提交
1755 1756
		if (wret)
			ret = wret;
1757
	}
C
Chris Mason 已提交
1758
	btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
1759
	return ret;
1760 1761
}

C
Chris Mason 已提交
1762 1763 1764 1765
/*
 * delete the item at the leaf level in path.  If that empties
 * the leaf, remove it from the tree
 */
1766 1767
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path)
1768 1769
{
	int slot;
C
Chris Mason 已提交
1770
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1771
	struct buffer_head *leaf_buf;
1772 1773
	int doff;
	int dsize;
C
Chris Mason 已提交
1774 1775
	int ret = 0;
	int wret;
1776
	u32 nritems;
1777

1778
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1779
	leaf = btrfs_buffer_leaf(leaf_buf);
1780
	slot = path->slots[0];
C
Chris Mason 已提交
1781 1782
	doff = btrfs_item_offset(leaf->items + slot);
	dsize = btrfs_item_size(leaf->items + slot);
1783
	nritems = btrfs_header_nritems(&leaf->header);
1784

1785
	if (slot != nritems - 1) {
1786
		int i;
C
Chris Mason 已提交
1787
		int data_end = leaf_data_end(root, leaf);
C
Chris Mason 已提交
1788 1789 1790 1791
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end + dsize,
			      btrfs_leaf_data(leaf) + data_end,
			      doff - data_end);
C
Chris Mason 已提交
1792
		for (i = slot + 1; i < nritems; i++) {
C
Chris Mason 已提交
1793
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1794 1795
			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
		}
C
Chris Mason 已提交
1796 1797 1798 1799
		btrfs_memmove(root, leaf, leaf->items + slot,
			      leaf->items + slot + 1,
			      sizeof(struct btrfs_item) *
			      (nritems - slot - 1));
1800
	}
1801 1802
	btrfs_set_header_nritems(&leaf->header, nritems - 1);
	nritems--;
C
Chris Mason 已提交
1803
	/* delete the leaf if we've emptied it */
1804
	if (nritems == 0) {
1805
		if (leaf_buf == root->node) {
1806
			btrfs_set_header_level(&leaf->header, 0);
1807
		} else {
1808
			clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1809
			wait_on_buffer(leaf_buf);
1810
			wret = del_ptr(trans, root, path, 1, path->slots[1]);
C
Chris Mason 已提交
1811 1812
			if (wret)
				ret = wret;
1813
			wret = btrfs_free_extent(trans, root,
1814
						 bh_blocknr(leaf_buf), 1, 1);
C
Chris Mason 已提交
1815 1816
			if (wret)
				ret = wret;
1817
		}
1818
	} else {
1819
		int used = leaf_space_used(leaf, 0, nritems);
C
Chris Mason 已提交
1820
		if (slot == 0) {
1821 1822
			wret = fixup_low_keys(trans, root, path,
					      &leaf->items[0].key, 1);
C
Chris Mason 已提交
1823 1824 1825 1826
			if (wret)
				ret = wret;
		}

C
Chris Mason 已提交
1827
		/* delete the leaf if it is mostly empty */
C
Chris Mason 已提交
1828
		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1829 1830 1831 1832
			/* push_leaf_left fixes the path.
			 * make sure the path still points to our leaf
			 * for possible call to del_ptr below
			 */
1833
			slot = path->slots[1];
C
Chris Mason 已提交
1834
			get_bh(leaf_buf);
1835
			wret = push_leaf_left(trans, root, path, 1);
1836
			if (wret < 0 && wret != -ENOSPC)
C
Chris Mason 已提交
1837
				ret = wret;
1838
			if (path->nodes[0] == leaf_buf &&
1839
			    btrfs_header_nritems(&leaf->header)) {
1840
				wret = push_leaf_right(trans, root, path, 1);
1841
				if (wret < 0 && wret != -ENOSPC)
C
Chris Mason 已提交
1842 1843
					ret = wret;
			}
1844
			if (btrfs_header_nritems(&leaf->header) == 0) {
1845
				u64 blocknr = bh_blocknr(leaf_buf);
1846
				clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1847
				wait_on_buffer(leaf_buf);
1848
				wret = del_ptr(trans, root, path, 1, slot);
C
Chris Mason 已提交
1849 1850
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1851
				btrfs_block_release(root, leaf_buf);
1852 1853
				wret = btrfs_free_extent(trans, root, blocknr,
							 1, 1);
C
Chris Mason 已提交
1854 1855
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1856
			} else {
C
Chris Mason 已提交
1857
				btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1858
				btrfs_block_release(root, leaf_buf);
1859
			}
1860
		} else {
C
Chris Mason 已提交
1861
			btrfs_mark_buffer_dirty(leaf_buf);
1862 1863
		}
	}
C
Chris Mason 已提交
1864
	return ret;
1865 1866
}

C
Chris Mason 已提交
1867 1868
/*
 * walk up the tree as far as required to find the next leaf.
C
Chris Mason 已提交
1869 1870
 * returns 0 if it found something or 1 if there are no greater leaves.
 * returns < 0 on io errors.
C
Chris Mason 已提交
1871
 */
C
Chris Mason 已提交
1872
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1873 1874 1875 1876
{
	int slot;
	int level = 1;
	u64 blocknr;
C
Chris Mason 已提交
1877 1878 1879
	struct buffer_head *c;
	struct btrfs_node *c_node;
	struct buffer_head *next = NULL;
1880

C
Chris Mason 已提交
1881
	while(level < BTRFS_MAX_LEVEL) {
1882
		if (!path->nodes[level])
C
Chris Mason 已提交
1883
			return 1;
1884 1885
		slot = path->slots[level] + 1;
		c = path->nodes[level];
C
Chris Mason 已提交
1886 1887
		c_node = btrfs_buffer_node(c);
		if (slot >= btrfs_header_nritems(&c_node->header)) {
1888 1889 1890
			level++;
			continue;
		}
C
Chris Mason 已提交
1891
		blocknr = btrfs_node_blockptr(c_node, slot);
C
Chris Mason 已提交
1892
		if (next)
C
Chris Mason 已提交
1893
			btrfs_block_release(root, next);
1894 1895 1896 1897 1898 1899 1900
		next = read_tree_block(root, blocknr);
		break;
	}
	path->slots[level] = slot;
	while(1) {
		level--;
		c = path->nodes[level];
C
Chris Mason 已提交
1901
		btrfs_block_release(root, c);
1902 1903 1904 1905
		path->nodes[level] = next;
		path->slots[level] = 0;
		if (!level)
			break;
1906
		next = read_tree_block(root,
C
Chris Mason 已提交
1907
		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1908 1909 1910
	}
	return 0;
}