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

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

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

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

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

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

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

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

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

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

	btrfs_disk_key_to_cpu(&k1, disk);

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

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

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

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

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

	if (nritems == 0)
		return 0;

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

C
Chris Mason 已提交
201 202
static int check_block(struct btrfs_root *root, struct btrfs_path *path,
			int level)
C
Chris Mason 已提交
203
{
C
Chris Mason 已提交
204 205 206 207
	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 已提交
208
	if (level == 0)
C
Chris Mason 已提交
209 210
		return check_leaf(root, path, level);
	return check_node(root, path, level);
C
Chris Mason 已提交
211 212
}

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

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

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

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

	if (level == 0)
		return 0;

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

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

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

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

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

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

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

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

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

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

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
/* 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 已提交
493 494 495 496 497 498 499 500
		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
			btrfs_cow_block(trans, root, left_buf, parent_buf,
					pslot - 1, &left_buf);
			left = btrfs_buffer_node(left_buf);
			wret = push_node_left(trans, root, left_buf, mid_buf);
		}
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
		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 已提交
532
		u32 right_nr;
533
		right = btrfs_buffer_node(right_buf);
C
Chris Mason 已提交
534 535 536 537 538 539 540 541 542 543
		right_nr = btrfs_header_nritems(&right->header);
		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
			wret = 1;
		} else {
			btrfs_cow_block(trans, root, right_buf,
					parent_buf, pslot + 1, &right_buf);
			right = btrfs_buffer_node(right_buf);
			wret = balance_node_right(trans, root,
						  right_buf, mid_buf);
		}
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
		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 已提交
570 571 572 573 574 575
/*
 * 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 已提交
576 577
 * be inserted, and 1 is returned.  If there are other errors during the
 * search a negative error number is returned.
C
Chris Mason 已提交
578 579 580 581
 *
 * 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 已提交
582
 */
583 584 585
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)
586
{
C
Chris Mason 已提交
587 588
	struct buffer_head *b;
	struct buffer_head *cow_buf;
C
Chris Mason 已提交
589
	struct btrfs_node *c;
590 591 592
	int slot;
	int ret;
	int level;
C
Chris Mason 已提交
593

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

C
Chris Mason 已提交
663 664 665 666 667 668
/*
 * 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 已提交
669 670 671
 *
 * 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 已提交
672
 */
673 674 675
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)
676 677
{
	int i;
C
Chris Mason 已提交
678
	int ret = 0;
C
Chris Mason 已提交
679 680
	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
		struct btrfs_node *t;
681
		int tslot = path->slots[i];
682
		if (!path->nodes[i])
683
			break;
C
Chris Mason 已提交
684
		t = btrfs_buffer_node(path->nodes[i]);
C
Chris Mason 已提交
685 686
		btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
		btrfs_mark_buffer_dirty(path->nodes[i]);
687 688 689
		if (tslot != 0)
			break;
	}
C
Chris Mason 已提交
690
	return ret;
691 692
}

C
Chris Mason 已提交
693 694
/*
 * try to push data from one node into the next node left in the
695
 * tree.
C
Chris Mason 已提交
696 697 698
 *
 * 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 已提交
699
 */
700
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
C
Chris Mason 已提交
701 702
			  *root, struct buffer_head *dst_buf, struct
			  buffer_head *src_buf)
703
{
C
Chris Mason 已提交
704 705
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
706
	int push_items = 0;
707 708
	int src_nritems;
	int dst_nritems;
C
Chris Mason 已提交
709
	int ret = 0;
710

711 712
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
713
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
714
	if (push_items <= 0) {
715
		return 1;
716
	}
717

718
	if (src_nritems < push_items)
719 720
		push_items = src_nritems;

C
Chris Mason 已提交
721 722
	btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
		     push_items * sizeof(struct btrfs_key_ptr));
723
	if (push_items < src_nritems) {
C
Chris Mason 已提交
724
		btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
C
Chris Mason 已提交
725
			(src_nritems - push_items) *
C
Chris Mason 已提交
726
			sizeof(struct btrfs_key_ptr));
727
	}
728 729
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
C
Chris Mason 已提交
730 731
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
732 733 734 735 736 737 738 739 740 741 742 743
	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
 */
744
static int balance_node_right(struct btrfs_trans_handle *trans, struct
C
Chris Mason 已提交
745 746
			      btrfs_root *root, struct buffer_head *dst_buf,
			      struct buffer_head *src_buf)
747
{
C
Chris Mason 已提交
748 749
	struct btrfs_node *src = btrfs_buffer_node(src_buf);
	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
750 751 752 753 754 755
	int push_items = 0;
	int max_push;
	int src_nritems;
	int dst_nritems;
	int ret = 0;

756 757
	src_nritems = btrfs_header_nritems(&src->header);
	dst_nritems = btrfs_header_nritems(&dst->header);
C
Chris Mason 已提交
758
	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
759 760 761 762 763 764 765 766 767 768 769
	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 已提交
770 771 772 773 774 775
	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));
776

777 778
	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
779

C
Chris Mason 已提交
780 781
	btrfs_mark_buffer_dirty(src_buf);
	btrfs_mark_buffer_dirty(dst_buf);
C
Chris Mason 已提交
782
	return ret;
783 784
}

C
Chris Mason 已提交
785 786 787 788
/*
 * 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 已提交
789 790
 *
 * returns zero on success or < 0 on failure.
C
Chris Mason 已提交
791
 */
792 793
static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int level)
C
Chris Mason 已提交
794
{
C
Chris Mason 已提交
795
	struct buffer_head *t;
C
Chris Mason 已提交
796 797
	struct btrfs_node *lower;
	struct btrfs_node *c;
C
Chris Mason 已提交
798
	struct btrfs_disk_key *lower_key;
C
Chris Mason 已提交
799 800 801 802

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

803
	t = btrfs_alloc_free_block(trans, root);
C
Chris Mason 已提交
804
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
805
	memset(c, 0, root->blocksize);
806 807
	btrfs_set_header_nritems(&c->header, 1);
	btrfs_set_header_level(&c->header, level);
808
	btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
809
	btrfs_set_header_generation(&c->header, trans->transid);
810
	btrfs_set_header_owner(&c->header, root->root_key.objectid);
C
Chris Mason 已提交
811
	lower = btrfs_buffer_node(path->nodes[level-1]);
C
Chris Mason 已提交
812 813
	memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(c->header.fsid));
814
	if (btrfs_is_leaf(lower))
C
Chris Mason 已提交
815
		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
C
Chris Mason 已提交
816
	else
C
Chris Mason 已提交
817
		lower_key = &lower->ptrs[0].key;
C
Chris Mason 已提交
818 819
	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
		     sizeof(struct btrfs_disk_key));
820
	btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
821

C
Chris Mason 已提交
822
	btrfs_mark_buffer_dirty(t);
823

C
Chris Mason 已提交
824
	/* the super has an extra ref to root->node */
C
Chris Mason 已提交
825
	btrfs_block_release(root, root->node);
C
Chris Mason 已提交
826
	root->node = t;
C
Chris Mason 已提交
827
	get_bh(t);
C
Chris Mason 已提交
828 829 830 831 832
	path->nodes[level] = t;
	path->slots[level] = 0;
	return 0;
}

C
Chris Mason 已提交
833 834 835
/*
 * worker function to insert a single pointer in a node.
 * the node should have enough room for the pointer already
C
Chris Mason 已提交
836
 *
C
Chris Mason 已提交
837 838
 * slot and level indicate where you want the key to go, and
 * blocknr is the block the key points to.
C
Chris Mason 已提交
839 840
 *
 * returns zero on success and < 0 on any error
C
Chris Mason 已提交
841
 */
842 843 844
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 已提交
845
{
C
Chris Mason 已提交
846
	struct btrfs_node *lower;
C
Chris Mason 已提交
847
	int nritems;
C
Chris Mason 已提交
848 849

	BUG_ON(!path->nodes[level]);
C
Chris Mason 已提交
850
	lower = btrfs_buffer_node(path->nodes[level]);
851
	nritems = btrfs_header_nritems(&lower->header);
C
Chris Mason 已提交
852 853
	if (slot > nritems)
		BUG();
C
Chris Mason 已提交
854
	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
C
Chris Mason 已提交
855 856
		BUG();
	if (slot != nritems) {
C
Chris Mason 已提交
857 858 859
		btrfs_memmove(root, lower, lower->ptrs + slot + 1,
			      lower->ptrs + slot,
			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
C
Chris Mason 已提交
860
	}
C
Chris Mason 已提交
861 862
	btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
		     key, sizeof(struct btrfs_disk_key));
863
	btrfs_set_node_blockptr(lower, slot, blocknr);
864
	btrfs_set_header_nritems(&lower->header, nritems + 1);
C
Chris Mason 已提交
865
	btrfs_mark_buffer_dirty(path->nodes[level]);
C
Chris Mason 已提交
866 867 868
	return 0;
}

C
Chris Mason 已提交
869 870 871 872 873 874
/*
 * 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 已提交
875 876
 *
 * returns 0 on success and < 0 on failure
C
Chris Mason 已提交
877
 */
878 879
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_path *path, int level)
880
{
C
Chris Mason 已提交
881
	struct buffer_head *t;
C
Chris Mason 已提交
882
	struct btrfs_node *c;
C
Chris Mason 已提交
883
	struct buffer_head *split_buffer;
C
Chris Mason 已提交
884
	struct btrfs_node *split;
885
	int mid;
C
Chris Mason 已提交
886
	int ret;
C
Chris Mason 已提交
887
	int wret;
888
	u32 c_nritems;
889

C
Chris Mason 已提交
890
	t = path->nodes[level];
C
Chris Mason 已提交
891
	c = btrfs_buffer_node(t);
C
Chris Mason 已提交
892 893
	if (t == root->node) {
		/* trying to split the root, lets make a new one */
894
		ret = insert_new_root(trans, root, path, level + 1);
C
Chris Mason 已提交
895 896
		if (ret)
			return ret;
897 898 899 900 901 902 903 904
	} 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;
905
	}
906

907
	c_nritems = btrfs_header_nritems(&c->header);
908
	split_buffer = btrfs_alloc_free_block(trans, root);
C
Chris Mason 已提交
909
	split = btrfs_buffer_node(split_buffer);
910
	btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
911
	btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
912
	btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer));
913
	btrfs_set_header_generation(&split->header, trans->transid);
914
	btrfs_set_header_owner(&split->header, root->root_key.objectid);
C
Chris Mason 已提交
915 916
	memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(split->header.fsid));
917
	mid = (c_nritems + 1) / 2;
C
Chris Mason 已提交
918 919
	btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
		     (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
920 921
	btrfs_set_header_nritems(&split->header, c_nritems - mid);
	btrfs_set_header_nritems(&c->header, mid);
C
Chris Mason 已提交
922 923
	ret = 0;

C
Chris Mason 已提交
924 925
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(split_buffer);
926
	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
927
			  bh_blocknr(split_buffer), path->slots[level + 1] + 1,
C
Chris Mason 已提交
928
			  level + 1);
C
Chris Mason 已提交
929 930 931
	if (wret)
		ret = wret;

C
Chris Mason 已提交
932
	if (path->slots[level] >= mid) {
C
Chris Mason 已提交
933
		path->slots[level] -= mid;
C
Chris Mason 已提交
934
		btrfs_block_release(root, t);
C
Chris Mason 已提交
935 936 937
		path->nodes[level] = split_buffer;
		path->slots[level + 1] += 1;
	} else {
C
Chris Mason 已提交
938
		btrfs_block_release(root, split_buffer);
939
	}
C
Chris Mason 已提交
940
	return ret;
941 942
}

C
Chris Mason 已提交
943 944 945 946 947
/*
 * 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 已提交
948
static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
949 950
{
	int data_len;
951 952
	int nritems = btrfs_header_nritems(&l->header);
	int end = min(nritems, start + nr) - 1;
953 954 955

	if (!nr)
		return 0;
C
Chris Mason 已提交
956 957 958
	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;
959
	WARN_ON(data_len < 0);
960 961 962
	return data_len;
}

963 964 965 966 967 968 969 970 971 972 973
/*
 * 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 已提交
974 975 976
/*
 * 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 已提交
977 978 979
 *
 * 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 已提交
980
 */
981 982
static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
			   *root, struct btrfs_path *path, int data_size)
C
Chris Mason 已提交
983
{
C
Chris Mason 已提交
984 985
	struct buffer_head *left_buf = path->nodes[0];
	struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
C
Chris Mason 已提交
986
	struct btrfs_leaf *right;
C
Chris Mason 已提交
987 988 989
	struct buffer_head *right_buf;
	struct buffer_head *upper;
	struct btrfs_node *upper_node;
C
Chris Mason 已提交
990 991 992 993 994
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
995
	struct btrfs_item *item;
996 997
	u32 left_nritems;
	u32 right_nritems;
C
Chris Mason 已提交
998 999 1000 1001 1002 1003

	slot = path->slots[1];
	if (!path->nodes[1]) {
		return 1;
	}
	upper = path->nodes[1];
C
Chris Mason 已提交
1004 1005
	upper_node = btrfs_buffer_node(upper);
	if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
C
Chris Mason 已提交
1006 1007
		return 1;
	}
C
Chris Mason 已提交
1008 1009 1010
	right_buf = read_tree_block(root,
		    btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1011
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1012
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1013
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1014 1015
		return 1;
	}
C
Chris Mason 已提交
1016
	/* cow and double check */
1017
	btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf);
C
Chris Mason 已提交
1018
	right = btrfs_buffer_leaf(right_buf);
C
Chris Mason 已提交
1019
	free_space = btrfs_leaf_free_space(root, right);
C
Chris Mason 已提交
1020
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1021
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1022 1023 1024
		return 1;
	}

1025
	left_nritems = btrfs_header_nritems(&left->header);
1026 1027 1028 1029 1030
	if (left_nritems == 0) {
		btrfs_block_release(root, right_buf);
		return 1;
	}
	for (i = left_nritems - 1; i >= 1; i--) {
C
Chris Mason 已提交
1031 1032 1033
		item = left->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1034 1035
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
C
Chris Mason 已提交
1036 1037
			break;
		push_items++;
C
Chris Mason 已提交
1038
		push_space += btrfs_item_size(item) + sizeof(*item);
C
Chris Mason 已提交
1039 1040
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1041
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1042 1043
		return 1;
	}
1044 1045
	if (push_items == left_nritems)
		WARN_ON(1);
1046
	right_nritems = btrfs_header_nritems(&right->header);
C
Chris Mason 已提交
1047
	/* push left to right */
C
Chris Mason 已提交
1048
	push_space = btrfs_item_end(left->items + left_nritems - push_items);
C
Chris Mason 已提交
1049
	push_space -= leaf_data_end(root, left);
C
Chris Mason 已提交
1050
	/* make room in the right data area */
C
Chris Mason 已提交
1051 1052 1053 1054 1055
	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 已提交
1056
	/* copy from the left data area */
C
Chris Mason 已提交
1057 1058 1059 1060 1061
	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 已提交
1062
		right_nritems * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1063
	/* copy the items from left to right */
C
Chris Mason 已提交
1064 1065 1066
	btrfs_memcpy(root, right, right->items, left->items +
		     left_nritems - push_items,
		     push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1067 1068

	/* update the item pointers */
1069 1070
	right_nritems += push_items;
	btrfs_set_header_nritems(&right->header, right_nritems);
C
Chris Mason 已提交
1071
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1072
	for (i = 0; i < right_nritems; i++) {
C
Chris Mason 已提交
1073 1074 1075
		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 已提交
1076
	}
1077 1078
	left_nritems -= push_items;
	btrfs_set_header_nritems(&left->header, left_nritems);
C
Chris Mason 已提交
1079

C
Chris Mason 已提交
1080 1081
	btrfs_mark_buffer_dirty(left_buf);
	btrfs_mark_buffer_dirty(right_buf);
1082

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

C
Chris Mason 已提交
1087
	/* then fixup the leaf pointer in the path */
1088 1089
	if (path->slots[0] >= left_nritems) {
		path->slots[0] -= left_nritems;
C
Chris Mason 已提交
1090
		btrfs_block_release(root, path->nodes[0]);
C
Chris Mason 已提交
1091 1092 1093
		path->nodes[0] = right_buf;
		path->slots[1] += 1;
	} else {
C
Chris Mason 已提交
1094
		btrfs_block_release(root, right_buf);
C
Chris Mason 已提交
1095 1096 1097
	}
	return 0;
}
C
Chris Mason 已提交
1098 1099 1100 1101
/*
 * 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
 */
1102 1103
static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
			  *root, struct btrfs_path *path, int data_size)
1104
{
C
Chris Mason 已提交
1105 1106 1107
	struct buffer_head *right_buf = path->nodes[0];
	struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
	struct buffer_head *t;
C
Chris Mason 已提交
1108
	struct btrfs_leaf *left;
1109 1110 1111 1112 1113
	int slot;
	int i;
	int free_space;
	int push_space = 0;
	int push_items = 0;
C
Chris Mason 已提交
1114
	struct btrfs_item *item;
1115
	u32 old_left_nritems;
C
Chris Mason 已提交
1116 1117
	int ret = 0;
	int wret;
1118 1119 1120 1121 1122 1123 1124 1125

	slot = path->slots[1];
	if (slot == 0) {
		return 1;
	}
	if (!path->nodes[1]) {
		return 1;
	}
C
Chris Mason 已提交
1126 1127 1128
	t = read_tree_block(root,
	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1129
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1130
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1131
		btrfs_block_release(root, t);
1132 1133
		return 1;
	}
C
Chris Mason 已提交
1134 1135

	/* cow and double check */
1136
	btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
C
Chris Mason 已提交
1137
	left = btrfs_buffer_leaf(t);
C
Chris Mason 已提交
1138
	free_space = btrfs_leaf_free_space(root, left);
C
Chris Mason 已提交
1139
	if (free_space < data_size + sizeof(struct btrfs_item)) {
C
Chris Mason 已提交
1140
		btrfs_block_release(root, t);
C
Chris Mason 已提交
1141 1142 1143
		return 1;
	}

1144 1145 1146 1147 1148 1149
	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++) {
1150 1151 1152
		item = right->items + i;
		if (path->slots[0] == i)
			push_space += data_size + sizeof(*item);
C
Chris Mason 已提交
1153 1154
		if (btrfs_item_size(item) + sizeof(*item) + push_space >
		    free_space)
1155 1156
			break;
		push_items++;
C
Chris Mason 已提交
1157
		push_space += btrfs_item_size(item) + sizeof(*item);
1158 1159
	}
	if (push_items == 0) {
C
Chris Mason 已提交
1160
		btrfs_block_release(root, t);
1161 1162
		return 1;
	}
1163 1164
	if (push_items == btrfs_header_nritems(&right->header))
		WARN_ON(1);
1165
	/* push data from right to left */
C
Chris Mason 已提交
1166 1167 1168
	btrfs_memcpy(root, left, left->items +
		     btrfs_header_nritems(&left->header),
		     right->items, push_items * sizeof(struct btrfs_item));
C
Chris Mason 已提交
1169
	push_space = BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1170
		     btrfs_item_offset(right->items + push_items -1);
C
Chris Mason 已提交
1171 1172 1173 1174 1175
	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);
1176
	old_left_nritems = btrfs_header_nritems(&left->header);
1177 1178
	BUG_ON(old_left_nritems < 0);

C
Chris Mason 已提交
1179
	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
C
Chris Mason 已提交
1180 1181 1182
		u32 ioff = btrfs_item_offset(left->items + i);
		btrfs_set_item_offset(left->items + i, ioff -
				     (BTRFS_LEAF_DATA_SIZE(root) -
C
Chris Mason 已提交
1183 1184
				      btrfs_item_offset(left->items +
						        old_left_nritems - 1)));
1185
	}
1186
	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1187 1188

	/* fixup right node */
C
Chris Mason 已提交
1189
	push_space = btrfs_item_offset(right->items + push_items - 1) -
C
Chris Mason 已提交
1190
		     leaf_data_end(root, right);
C
Chris Mason 已提交
1191 1192 1193 1194 1195
	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,
1196
		(btrfs_header_nritems(&right->header) - push_items) *
C
Chris Mason 已提交
1197
		sizeof(struct btrfs_item));
1198 1199 1200
	btrfs_set_header_nritems(&right->header,
				 btrfs_header_nritems(&right->header) -
				 push_items);
C
Chris Mason 已提交
1201
	push_space = BTRFS_LEAF_DATA_SIZE(root);
1202

1203
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1204 1205 1206
		btrfs_set_item_offset(right->items + i, push_space -
				      btrfs_item_size(right->items + i));
		push_space = btrfs_item_offset(right->items + i);
1207
	}
1208

C
Chris Mason 已提交
1209 1210
	btrfs_mark_buffer_dirty(t);
	btrfs_mark_buffer_dirty(right_buf);
1211
	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
C
Chris Mason 已提交
1212 1213
	if (wret)
		ret = wret;
1214 1215 1216 1217

	/* then fixup the leaf pointer in the path */
	if (path->slots[0] < push_items) {
		path->slots[0] += old_left_nritems;
C
Chris Mason 已提交
1218
		btrfs_block_release(root, path->nodes[0]);
1219
		path->nodes[0] = t;
1220 1221
		path->slots[1] -= 1;
	} else {
C
Chris Mason 已提交
1222
		btrfs_block_release(root, t);
1223 1224
		path->slots[0] -= push_items;
	}
1225
	BUG_ON(path->slots[0] < 0);
C
Chris Mason 已提交
1226
	return ret;
1227 1228
}

C
Chris Mason 已提交
1229 1230 1231
/*
 * 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 已提交
1232 1233
 *
 * returns 0 if all went well and < 0 on failure.
C
Chris Mason 已提交
1234
 */
1235
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1236 1237
		      *root, struct btrfs_key *ins_key,
		      struct btrfs_path *path, int data_size)
1238
{
C
Chris Mason 已提交
1239
	struct buffer_head *l_buf;
C
Chris Mason 已提交
1240
	struct btrfs_leaf *l;
1241
	u32 nritems;
1242 1243
	int mid;
	int slot;
C
Chris Mason 已提交
1244
	struct btrfs_leaf *right;
C
Chris Mason 已提交
1245
	struct buffer_head *right_buffer;
C
Chris Mason 已提交
1246
	int space_needed = data_size + sizeof(struct btrfs_item);
1247 1248 1249
	int data_copy_size;
	int rt_data_off;
	int i;
1250
	int ret = 0;
C
Chris Mason 已提交
1251
	int wret;
1252 1253
	int double_split = 0;
	struct btrfs_disk_key disk_key;
C
Chris Mason 已提交
1254

C
Chris Mason 已提交
1255
	/* first try to make some room by pushing left and right */
1256
	wret = push_leaf_left(trans, root, path, data_size);
C
Chris Mason 已提交
1257 1258 1259
	if (wret < 0)
		return wret;
	if (wret) {
1260
		wret = push_leaf_right(trans, root, path, data_size);
C
Chris Mason 已提交
1261 1262 1263
		if (wret < 0)
			return wret;
	}
C
Chris Mason 已提交
1264
	l_buf = path->nodes[0];
C
Chris Mason 已提交
1265
	l = btrfs_buffer_leaf(l_buf);
C
Chris Mason 已提交
1266 1267

	/* did the pushes work? */
C
Chris Mason 已提交
1268 1269
	if (btrfs_leaf_free_space(root, l) >=
	    sizeof(struct btrfs_item) + data_size)
C
Chris Mason 已提交
1270 1271
		return 0;

C
Chris Mason 已提交
1272
	if (!path->nodes[1]) {
1273
		ret = insert_new_root(trans, root, path, 1);
C
Chris Mason 已提交
1274 1275 1276
		if (ret)
			return ret;
	}
1277
	slot = path->slots[0];
1278
	nritems = btrfs_header_nritems(&l->header);
1279
	mid = (nritems + 1)/ 2;
1280
	right_buffer = btrfs_alloc_free_block(trans, root);
1281
	BUG_ON(!right_buffer);
C
Chris Mason 已提交
1282
	right = btrfs_buffer_leaf(right_buffer);
C
Chris Mason 已提交
1283
	memset(&right->header, 0, sizeof(right->header));
1284
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1285
	btrfs_set_header_generation(&right->header, trans->transid);
1286
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1287
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1288 1289
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1290 1291 1292 1293 1294 1295 1296 1297 1298
	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,
1299
						  bh_blocknr(right_buffer),
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
						  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,
1320
						  bh_blocknr(right_buffer),
1321 1322 1323 1324 1325 1326 1327
						  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;
1328 1329 1330 1331 1332 1333
				if (path->slots[1] == 0) {
					wret = fixup_low_keys(trans, root,
					           path, &disk_key, 1);
					if (wret)
						ret = wret;
				}
1334 1335 1336 1337 1338 1339 1340
				return ret;
			}
			mid = slot;
			double_split = 1;
		}
	}
	btrfs_set_header_nritems(&right->header, nritems - mid);
C
Chris Mason 已提交
1341 1342
	data_copy_size = btrfs_item_end(l->items + mid) -
			 leaf_data_end(root, l);
C
Chris Mason 已提交
1343 1344 1345 1346 1347 1348
	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 已提交
1349 1350
	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
		      btrfs_item_end(l->items + mid);
C
Chris Mason 已提交
1351

C
Chris Mason 已提交
1352
	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
C
Chris Mason 已提交
1353
		u32 ioff = btrfs_item_offset(right->items + i);
C
Chris Mason 已提交
1354 1355
		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
	}
C
Chris Mason 已提交
1356

1357
	btrfs_set_header_nritems(&l->header, mid);
C
Chris Mason 已提交
1358
	ret = 0;
1359
	wret = insert_ptr(trans, root, path, &right->items[0].key,
1360
			  bh_blocknr(right_buffer), path->slots[1] + 1, 1);
C
Chris Mason 已提交
1361 1362
	if (wret)
		ret = wret;
C
Chris Mason 已提交
1363 1364
	btrfs_mark_buffer_dirty(right_buffer);
	btrfs_mark_buffer_dirty(l_buf);
1365
	BUG_ON(path->slots[0] != slot);
1366
	if (mid <= slot) {
C
Chris Mason 已提交
1367
		btrfs_block_release(root, path->nodes[0]);
1368
		path->nodes[0] = right_buffer;
1369 1370
		path->slots[0] -= mid;
		path->slots[1] += 1;
1371
	} else
C
Chris Mason 已提交
1372
		btrfs_block_release(root, right_buffer);
1373
	BUG_ON(path->slots[0] < 0);
1374 1375 1376 1377 1378 1379 1380

	if (!double_split)
		return ret;
	right_buffer = btrfs_alloc_free_block(trans, root);
	BUG_ON(!right_buffer);
	right = btrfs_buffer_leaf(right_buffer);
	memset(&right->header, 0, sizeof(right->header));
1381
	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1382
	btrfs_set_header_generation(&right->header, trans->transid);
1383
	btrfs_set_header_owner(&right->header, root->root_key.objectid);
1384
	btrfs_set_header_level(&right->header, 0);
C
Chris Mason 已提交
1385 1386
	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
	       sizeof(right->header.fsid));
1387 1388 1389 1390
	btrfs_cpu_key_to_disk(&disk_key, ins_key);
	btrfs_set_header_nritems(&right->header, 0);
	wret = insert_ptr(trans, root, path,
			  &disk_key,
1391
			  bh_blocknr(right_buffer),
1392 1393 1394
			  path->slots[1], 1);
	if (wret)
		ret = wret;
1395 1396 1397 1398 1399
	if (path->slots[1] == 0) {
		wret = fixup_low_keys(trans, root, path, &disk_key, 1);
		if (wret)
			ret = wret;
	}
1400 1401 1402 1403 1404
	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);
1405 1406 1407
	return ret;
}

C
Chris Mason 已提交
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463
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;
}

1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
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 已提交
1518 1519 1520 1521
/*
 * 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.
 */
1522 1523 1524
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)
1525
{
C
Chris Mason 已提交
1526
	int ret = 0;
1527
	int slot;
1528
	int slot_orig;
C
Chris Mason 已提交
1529
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1530
	struct buffer_head *leaf_buf;
1531
	u32 nritems;
1532
	unsigned int data_end;
C
Chris Mason 已提交
1533 1534 1535
	struct btrfs_disk_key disk_key;

	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1536

C
Chris Mason 已提交
1537
	/* create a root if there isn't one */
C
Chris Mason 已提交
1538
	if (!root->node)
C
Chris Mason 已提交
1539
		BUG();
1540
	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1541
	if (ret == 0) {
1542
		return -EEXIST;
C
Chris Mason 已提交
1543
	}
1544 1545
	if (ret < 0)
		goto out;
1546

1547 1548
	slot_orig = path->slots[0];
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1549
	leaf = btrfs_buffer_leaf(leaf_buf);
C
Chris Mason 已提交
1550

1551
	nritems = btrfs_header_nritems(&leaf->header);
C
Chris Mason 已提交
1552
	data_end = leaf_data_end(root, leaf);
1553

C
Chris Mason 已提交
1554
	if (btrfs_leaf_free_space(root, leaf) <
1555
	    sizeof(struct btrfs_item) + data_size) {
1556
		BUG();
1557
	}
1558
	slot = path->slots[0];
1559
	BUG_ON(slot < 0);
1560 1561
	if (slot != nritems) {
		int i;
C
Chris Mason 已提交
1562
		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1563 1564 1565 1566 1567

		/*
		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
		 */
		/* first correct the data pointers */
C
Chris Mason 已提交
1568
		for (i = slot; i < nritems; i++) {
C
Chris Mason 已提交
1569
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1570 1571 1572
			btrfs_set_item_offset(leaf->items + i,
					      ioff - data_size);
		}
1573 1574

		/* shift the items */
C
Chris Mason 已提交
1575 1576 1577
		btrfs_memmove(root, leaf, leaf->items + slot + 1,
			      leaf->items + slot,
			      (nritems - slot) * sizeof(struct btrfs_item));
1578 1579

		/* shift the data */
C
Chris Mason 已提交
1580 1581 1582
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end - data_size, btrfs_leaf_data(leaf) +
			      data_end, old_data - data_end);
1583 1584
		data_end = old_data;
	}
1585
	/* setup the item for the new data */
C
Chris Mason 已提交
1586 1587
	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
		     sizeof(struct btrfs_disk_key));
C
Chris Mason 已提交
1588 1589
	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
	btrfs_set_item_size(leaf->items + slot, data_size);
1590
	btrfs_set_header_nritems(&leaf->header, nritems + 1);
C
Chris Mason 已提交
1591
	btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1592 1593

	ret = 0;
1594
	if (slot == 0)
1595
		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
C
Chris Mason 已提交
1596

C
Chris Mason 已提交
1597
	if (btrfs_leaf_free_space(root, leaf) < 0)
1598
		BUG();
1599
	check_leaf(root, path, 0);
1600
out:
1601 1602 1603 1604 1605 1606 1607
	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.
 */
1608 1609 1610
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
		      *root, struct btrfs_key *cpu_key, void *data, u32
		      data_size)
1611 1612
{
	int ret = 0;
C
Chris Mason 已提交
1613
	struct btrfs_path *path;
1614 1615
	u8 *ptr;

C
Chris Mason 已提交
1616 1617 1618 1619
	path = btrfs_alloc_path();
	BUG_ON(!path);
	btrfs_init_path(path);
	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
1620
	if (!ret) {
C
Chris Mason 已提交
1621 1622 1623
		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 已提交
1624
			     ptr, data, data_size);
C
Chris Mason 已提交
1625
		btrfs_mark_buffer_dirty(path->nodes[0]);
1626
	}
C
Chris Mason 已提交
1627 1628
	btrfs_release_path(root, path);
	btrfs_free_path(path);
C
Chris Mason 已提交
1629
	return ret;
1630 1631
}

C
Chris Mason 已提交
1632
/*
C
Chris Mason 已提交
1633
 * delete the pointer from a given node.
C
Chris Mason 已提交
1634 1635 1636 1637 1638
 *
 * 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.
 */
1639 1640
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path, int level, int slot)
1641
{
C
Chris Mason 已提交
1642
	struct btrfs_node *node;
C
Chris Mason 已提交
1643
	struct buffer_head *parent = path->nodes[level];
1644
	u32 nritems;
C
Chris Mason 已提交
1645
	int ret = 0;
1646
	int wret;
1647

C
Chris Mason 已提交
1648
	node = btrfs_buffer_node(parent);
1649
	nritems = btrfs_header_nritems(&node->header);
1650
	if (slot != nritems -1) {
C
Chris Mason 已提交
1651 1652 1653 1654
		btrfs_memmove(root, node, node->ptrs + slot,
			      node->ptrs + slot + 1,
			      sizeof(struct btrfs_key_ptr) *
			      (nritems - slot - 1));
1655
	}
1656 1657 1658
	nritems--;
	btrfs_set_header_nritems(&node->header, nritems);
	if (nritems == 0 && parent == root->node) {
C
Chris Mason 已提交
1659 1660
		struct btrfs_header *header = btrfs_buffer_header(root->node);
		BUG_ON(btrfs_header_level(header) != 1);
1661
		/* just turn the root into a leaf and break */
C
Chris Mason 已提交
1662
		btrfs_set_header_level(header, 0);
1663
	} else if (slot == 0) {
1664
		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
C
Chris Mason 已提交
1665
				      level + 1);
C
Chris Mason 已提交
1666 1667
		if (wret)
			ret = wret;
1668
	}
C
Chris Mason 已提交
1669
	btrfs_mark_buffer_dirty(parent);
C
Chris Mason 已提交
1670
	return ret;
1671 1672
}

C
Chris Mason 已提交
1673 1674 1675 1676
/*
 * delete the item at the leaf level in path.  If that empties
 * the leaf, remove it from the tree
 */
1677 1678
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		   struct btrfs_path *path)
1679 1680
{
	int slot;
C
Chris Mason 已提交
1681
	struct btrfs_leaf *leaf;
C
Chris Mason 已提交
1682
	struct buffer_head *leaf_buf;
1683 1684
	int doff;
	int dsize;
C
Chris Mason 已提交
1685 1686
	int ret = 0;
	int wret;
1687
	u32 nritems;
1688

1689
	leaf_buf = path->nodes[0];
C
Chris Mason 已提交
1690
	leaf = btrfs_buffer_leaf(leaf_buf);
1691
	slot = path->slots[0];
C
Chris Mason 已提交
1692 1693
	doff = btrfs_item_offset(leaf->items + slot);
	dsize = btrfs_item_size(leaf->items + slot);
1694
	nritems = btrfs_header_nritems(&leaf->header);
1695

1696
	if (slot != nritems - 1) {
1697
		int i;
C
Chris Mason 已提交
1698
		int data_end = leaf_data_end(root, leaf);
C
Chris Mason 已提交
1699 1700 1701 1702
		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
			      data_end + dsize,
			      btrfs_leaf_data(leaf) + data_end,
			      doff - data_end);
C
Chris Mason 已提交
1703
		for (i = slot + 1; i < nritems; i++) {
C
Chris Mason 已提交
1704
			u32 ioff = btrfs_item_offset(leaf->items + i);
C
Chris Mason 已提交
1705 1706
			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
		}
C
Chris Mason 已提交
1707 1708 1709 1710
		btrfs_memmove(root, leaf, leaf->items + slot,
			      leaf->items + slot + 1,
			      sizeof(struct btrfs_item) *
			      (nritems - slot - 1));
1711
	}
1712 1713
	btrfs_set_header_nritems(&leaf->header, nritems - 1);
	nritems--;
C
Chris Mason 已提交
1714
	/* delete the leaf if we've emptied it */
1715
	if (nritems == 0) {
1716
		if (leaf_buf == root->node) {
1717
			btrfs_set_header_level(&leaf->header, 0);
1718
		} else {
1719
			clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1720
			wait_on_buffer(leaf_buf);
1721
			wret = del_ptr(trans, root, path, 1, path->slots[1]);
C
Chris Mason 已提交
1722 1723
			if (wret)
				ret = wret;
1724
			wret = btrfs_free_extent(trans, root,
1725
						 bh_blocknr(leaf_buf), 1, 1);
C
Chris Mason 已提交
1726 1727
			if (wret)
				ret = wret;
1728
		}
1729
	} else {
1730
		int used = leaf_space_used(leaf, 0, nritems);
C
Chris Mason 已提交
1731
		if (slot == 0) {
1732 1733
			wret = fixup_low_keys(trans, root, path,
					      &leaf->items[0].key, 1);
C
Chris Mason 已提交
1734 1735 1736 1737
			if (wret)
				ret = wret;
		}

C
Chris Mason 已提交
1738
		/* delete the leaf if it is mostly empty */
C
Chris Mason 已提交
1739
		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1740 1741 1742 1743
			/* push_leaf_left fixes the path.
			 * make sure the path still points to our leaf
			 * for possible call to del_ptr below
			 */
1744
			slot = path->slots[1];
C
Chris Mason 已提交
1745
			get_bh(leaf_buf);
1746
			wret = push_leaf_left(trans, root, path, 1);
C
Chris Mason 已提交
1747 1748
			if (wret < 0)
				ret = wret;
1749
			if (path->nodes[0] == leaf_buf &&
1750
			    btrfs_header_nritems(&leaf->header)) {
1751
				wret = push_leaf_right(trans, root, path, 1);
C
Chris Mason 已提交
1752 1753 1754
				if (wret < 0)
					ret = wret;
			}
1755
			if (btrfs_header_nritems(&leaf->header) == 0) {
1756
				u64 blocknr = bh_blocknr(leaf_buf);
1757
				clean_tree_block(trans, root, leaf_buf);
C
Chris Mason 已提交
1758
				wait_on_buffer(leaf_buf);
1759
				wret = del_ptr(trans, root, path, 1, slot);
C
Chris Mason 已提交
1760 1761
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1762
				btrfs_block_release(root, leaf_buf);
1763 1764
				wret = btrfs_free_extent(trans, root, blocknr,
							 1, 1);
C
Chris Mason 已提交
1765 1766
				if (wret)
					ret = wret;
C
Chris Mason 已提交
1767
			} else {
C
Chris Mason 已提交
1768
				btrfs_mark_buffer_dirty(leaf_buf);
C
Chris Mason 已提交
1769
				btrfs_block_release(root, leaf_buf);
1770
			}
1771
		} else {
C
Chris Mason 已提交
1772
			btrfs_mark_buffer_dirty(leaf_buf);
1773 1774
		}
	}
C
Chris Mason 已提交
1775
	return ret;
1776 1777
}

C
Chris Mason 已提交
1778 1779
/*
 * walk up the tree as far as required to find the next leaf.
C
Chris Mason 已提交
1780 1781
 * returns 0 if it found something or 1 if there are no greater leaves.
 * returns < 0 on io errors.
C
Chris Mason 已提交
1782
 */
C
Chris Mason 已提交
1783
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1784 1785 1786 1787
{
	int slot;
	int level = 1;
	u64 blocknr;
C
Chris Mason 已提交
1788 1789 1790
	struct buffer_head *c;
	struct btrfs_node *c_node;
	struct buffer_head *next = NULL;
1791

C
Chris Mason 已提交
1792
	while(level < BTRFS_MAX_LEVEL) {
1793
		if (!path->nodes[level])
C
Chris Mason 已提交
1794
			return 1;
1795 1796
		slot = path->slots[level] + 1;
		c = path->nodes[level];
C
Chris Mason 已提交
1797 1798
		c_node = btrfs_buffer_node(c);
		if (slot >= btrfs_header_nritems(&c_node->header)) {
1799 1800 1801
			level++;
			continue;
		}
C
Chris Mason 已提交
1802
		blocknr = btrfs_node_blockptr(c_node, slot);
C
Chris Mason 已提交
1803
		if (next)
C
Chris Mason 已提交
1804
			btrfs_block_release(root, next);
1805 1806 1807 1808 1809 1810 1811
		next = read_tree_block(root, blocknr);
		break;
	}
	path->slots[level] = slot;
	while(1) {
		level--;
		c = path->nodes[level];
C
Chris Mason 已提交
1812
		btrfs_block_release(root, c);
1813 1814 1815 1816
		path->nodes[level] = next;
		path->slots[level] = 0;
		if (!level)
			break;
1817
		next = read_tree_block(root,
C
Chris Mason 已提交
1818
		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1819 1820 1821
	}
	return 0;
}