xref: /openbmc/linux/fs/btrfs/ctree.c (revision b18c6685)
12e635a27SChris Mason #include <linux/module.h>
2eb60ceacSChris Mason #include "ctree.h"
3eb60ceacSChris Mason #include "disk-io.h"
47f5c1516SChris Mason #include "transaction.h"
59a8dd150SChris Mason 
6e089f05cSChris Mason static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
7e089f05cSChris Mason 		      *root, struct btrfs_path *path, int level);
8e089f05cSChris Mason static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
9d4dbff95SChris Mason 		      *root, struct btrfs_key *ins_key,
10d4dbff95SChris Mason 		      struct btrfs_path *path, int data_size);
11e089f05cSChris Mason static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
12e20d96d6SChris Mason 			  *root, struct buffer_head *dst, struct buffer_head
13e089f05cSChris Mason 			  *src);
14e089f05cSChris Mason static int balance_node_right(struct btrfs_trans_handle *trans, struct
15e20d96d6SChris Mason 			      btrfs_root *root, struct buffer_head *dst_buf,
16e20d96d6SChris Mason 			      struct buffer_head *src_buf);
17e089f05cSChris Mason static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
18e089f05cSChris Mason 		   struct btrfs_path *path, int level, int slot);
19d97e63b6SChris Mason 
20df24a2b9SChris Mason inline void btrfs_init_path(struct btrfs_path *p)
21df24a2b9SChris Mason {
22df24a2b9SChris Mason 	memset(p, 0, sizeof(*p));
23df24a2b9SChris Mason }
24df24a2b9SChris Mason 
252c90e5d6SChris Mason struct btrfs_path *btrfs_alloc_path(void)
262c90e5d6SChris Mason {
27df24a2b9SChris Mason 	struct btrfs_path *path;
28df24a2b9SChris Mason 	path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
29df24a2b9SChris Mason 	if (path)
30df24a2b9SChris Mason 		btrfs_init_path(path);
31df24a2b9SChris Mason 	return path;
322c90e5d6SChris Mason }
332c90e5d6SChris Mason 
342c90e5d6SChris Mason void btrfs_free_path(struct btrfs_path *p)
352c90e5d6SChris Mason {
36df24a2b9SChris Mason 	btrfs_release_path(NULL, p);
372c90e5d6SChris Mason 	kmem_cache_free(btrfs_path_cachep, p);
382c90e5d6SChris Mason }
392c90e5d6SChris Mason 
40234b63a0SChris Mason void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
41eb60ceacSChris Mason {
42eb60ceacSChris Mason 	int i;
43234b63a0SChris Mason 	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
44eb60ceacSChris Mason 		if (!p->nodes[i])
45eb60ceacSChris Mason 			break;
46234b63a0SChris Mason 		btrfs_block_release(root, p->nodes[i]);
47eb60ceacSChris Mason 	}
48aa5d6bedSChris Mason 	memset(p, 0, sizeof(*p));
49eb60ceacSChris Mason }
50eb60ceacSChris Mason 
51e089f05cSChris Mason static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
52e20d96d6SChris Mason 			   *root, struct buffer_head *buf, struct buffer_head
53e20d96d6SChris Mason 			   *parent, int parent_slot, struct buffer_head
54e089f05cSChris Mason 			   **cow_ret)
5502217ed2SChris Mason {
56e20d96d6SChris Mason 	struct buffer_head *cow;
57e20d96d6SChris Mason 	struct btrfs_node *cow_node;
5802217ed2SChris Mason 
597f5c1516SChris Mason 	if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
607f5c1516SChris Mason 				    trans->transid) {
6102217ed2SChris Mason 		*cow_ret = buf;
6202217ed2SChris Mason 		return 0;
6302217ed2SChris Mason 	}
64e089f05cSChris Mason 	cow = btrfs_alloc_free_block(trans, root);
65e20d96d6SChris Mason 	cow_node = btrfs_buffer_node(cow);
662c90e5d6SChris Mason 	if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
672c90e5d6SChris Mason 		WARN_ON(1);
68e20d96d6SChris Mason 	memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
697eccb903SChris Mason 	btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow));
707f5c1516SChris Mason 	btrfs_set_header_generation(&cow_node->header, trans->transid);
71e089f05cSChris Mason 	btrfs_inc_ref(trans, root, buf);
7202217ed2SChris Mason 	if (buf == root->node) {
7302217ed2SChris Mason 		root->node = cow;
74e20d96d6SChris Mason 		get_bh(cow);
752c90e5d6SChris Mason 		if (buf != root->commit_root) {
767eccb903SChris Mason 			btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
772c90e5d6SChris Mason 		}
78234b63a0SChris Mason 		btrfs_block_release(root, buf);
7902217ed2SChris Mason 	} else {
80e20d96d6SChris Mason 		btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
817eccb903SChris Mason 					bh_blocknr(cow));
82d6025579SChris Mason 		btrfs_mark_buffer_dirty(parent);
837eccb903SChris Mason 		btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
8402217ed2SChris Mason 	}
85234b63a0SChris Mason 	btrfs_block_release(root, buf);
86df24a2b9SChris Mason 	mark_buffer_dirty(cow);
872c90e5d6SChris Mason 	*cow_ret = cow;
8802217ed2SChris Mason 	return 0;
8902217ed2SChris Mason }
9002217ed2SChris Mason 
9174123bd7SChris Mason /*
9274123bd7SChris Mason  * The leaf data grows from end-to-front in the node.
9374123bd7SChris Mason  * this returns the address of the start of the last item,
9474123bd7SChris Mason  * which is the stop of the leaf data stack
9574123bd7SChris Mason  */
96123abc88SChris Mason static inline unsigned int leaf_data_end(struct btrfs_root *root,
97123abc88SChris Mason 					 struct btrfs_leaf *leaf)
98be0e5c09SChris Mason {
997518a238SChris Mason 	u32 nr = btrfs_header_nritems(&leaf->header);
100be0e5c09SChris Mason 	if (nr == 0)
101123abc88SChris Mason 		return BTRFS_LEAF_DATA_SIZE(root);
1020783fcfcSChris Mason 	return btrfs_item_offset(leaf->items + nr - 1);
103be0e5c09SChris Mason }
104be0e5c09SChris Mason 
10574123bd7SChris Mason /*
10674123bd7SChris Mason  * compare two keys in a memcmp fashion
10774123bd7SChris Mason  */
1089aca1d51SChris Mason static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
109be0e5c09SChris Mason {
110e2fa7227SChris Mason 	struct btrfs_key k1;
111e2fa7227SChris Mason 
112e2fa7227SChris Mason 	btrfs_disk_key_to_cpu(&k1, disk);
113e2fa7227SChris Mason 
114e2fa7227SChris Mason 	if (k1.objectid > k2->objectid)
115be0e5c09SChris Mason 		return 1;
116e2fa7227SChris Mason 	if (k1.objectid < k2->objectid)
117be0e5c09SChris Mason 		return -1;
118a8a2ee0cSChris Mason 	if (k1.offset > k2->offset)
119a8a2ee0cSChris Mason 		return 1;
120a8a2ee0cSChris Mason 	if (k1.offset < k2->offset)
121a8a2ee0cSChris Mason 		return -1;
122f254e52cSChris Mason 	if (k1.flags > k2->flags)
123f254e52cSChris Mason 		return 1;
124f254e52cSChris Mason 	if (k1.flags < k2->flags)
125f254e52cSChris Mason 		return -1;
126be0e5c09SChris Mason 	return 0;
127be0e5c09SChris Mason }
12874123bd7SChris Mason 
129123abc88SChris Mason static int check_node(struct btrfs_root *root, struct btrfs_path *path,
130123abc88SChris Mason 		      int level)
131aa5d6bedSChris Mason {
132aa5d6bedSChris Mason 	int i;
133234b63a0SChris Mason 	struct btrfs_node *parent = NULL;
134e20d96d6SChris Mason 	struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
135aa5d6bedSChris Mason 	int parent_slot;
1367518a238SChris Mason 	u32 nritems = btrfs_header_nritems(&node->header);
137aa5d6bedSChris Mason 
138aa5d6bedSChris Mason 	if (path->nodes[level + 1])
139e20d96d6SChris Mason 		parent = btrfs_buffer_node(path->nodes[level + 1]);
140aa5d6bedSChris Mason 	parent_slot = path->slots[level + 1];
1417518a238SChris Mason 	BUG_ON(nritems == 0);
1427518a238SChris Mason 	if (parent) {
143e2fa7227SChris Mason 		struct btrfs_disk_key *parent_key;
144123abc88SChris Mason 		parent_key = &parent->ptrs[parent_slot].key;
145123abc88SChris Mason 		BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
146e2fa7227SChris Mason 			      sizeof(struct btrfs_disk_key)));
1471d4f8a0cSChris Mason 		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
1487518a238SChris Mason 		       btrfs_header_blocknr(&node->header));
149aa5d6bedSChris Mason 	}
150123abc88SChris Mason 	BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
1517518a238SChris Mason 	for (i = 0; nritems > 1 && i < nritems - 2; i++) {
152e2fa7227SChris Mason 		struct btrfs_key cpukey;
153123abc88SChris Mason 		btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[i + 1].key);
154123abc88SChris Mason 		BUG_ON(comp_keys(&node->ptrs[i].key, &cpukey) >= 0);
155aa5d6bedSChris Mason 	}
156aa5d6bedSChris Mason 	return 0;
157aa5d6bedSChris Mason }
158aa5d6bedSChris Mason 
159123abc88SChris Mason static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
160123abc88SChris Mason 		      int level)
161aa5d6bedSChris Mason {
162aa5d6bedSChris Mason 	int i;
163e20d96d6SChris Mason 	struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
164234b63a0SChris Mason 	struct btrfs_node *parent = NULL;
165aa5d6bedSChris Mason 	int parent_slot;
1667518a238SChris Mason 	u32 nritems = btrfs_header_nritems(&leaf->header);
167aa5d6bedSChris Mason 
168aa5d6bedSChris Mason 	if (path->nodes[level + 1])
169e20d96d6SChris Mason 		parent = btrfs_buffer_node(path->nodes[level + 1]);
170aa5d6bedSChris Mason 	parent_slot = path->slots[level + 1];
171123abc88SChris Mason 	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
1727518a238SChris Mason 
1737518a238SChris Mason 	if (nritems == 0)
1747518a238SChris Mason 		return 0;
1757518a238SChris Mason 
1767518a238SChris Mason 	if (parent) {
177e2fa7227SChris Mason 		struct btrfs_disk_key *parent_key;
178123abc88SChris Mason 		parent_key = &parent->ptrs[parent_slot].key;
179aa5d6bedSChris Mason 		BUG_ON(memcmp(parent_key, &leaf->items[0].key,
180e2fa7227SChris Mason 		       sizeof(struct btrfs_disk_key)));
1811d4f8a0cSChris Mason 		BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
1827518a238SChris Mason 		       btrfs_header_blocknr(&leaf->header));
183aa5d6bedSChris Mason 	}
1847518a238SChris Mason 	for (i = 0; nritems > 1 && i < nritems - 2; i++) {
185e2fa7227SChris Mason 		struct btrfs_key cpukey;
186e2fa7227SChris Mason 		btrfs_disk_key_to_cpu(&cpukey, &leaf->items[i + 1].key);
187aa5d6bedSChris Mason 		BUG_ON(comp_keys(&leaf->items[i].key,
188e2fa7227SChris Mason 		                 &cpukey) >= 0);
1890783fcfcSChris Mason 		BUG_ON(btrfs_item_offset(leaf->items + i) !=
1900783fcfcSChris Mason 			btrfs_item_end(leaf->items + i + 1));
191aa5d6bedSChris Mason 		if (i == 0) {
1920783fcfcSChris Mason 			BUG_ON(btrfs_item_offset(leaf->items + i) +
1930783fcfcSChris Mason 			       btrfs_item_size(leaf->items + i) !=
194123abc88SChris Mason 			       BTRFS_LEAF_DATA_SIZE(root));
195aa5d6bedSChris Mason 		}
196aa5d6bedSChris Mason 	}
197aa5d6bedSChris Mason 	return 0;
198aa5d6bedSChris Mason }
199aa5d6bedSChris Mason 
200123abc88SChris Mason static int check_block(struct btrfs_root *root, struct btrfs_path *path,
201123abc88SChris Mason 			int level)
202aa5d6bedSChris Mason {
2033eb0314dSChris Mason 	struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
2043eb0314dSChris Mason 	if (memcmp(node->header.fsid, root->fs_info->disk_super->fsid,
2053eb0314dSChris Mason 		   sizeof(node->header.fsid)))
2063eb0314dSChris Mason 		BUG();
207aa5d6bedSChris Mason 	if (level == 0)
208123abc88SChris Mason 		return check_leaf(root, path, level);
209123abc88SChris Mason 	return check_node(root, path, level);
210aa5d6bedSChris Mason }
211aa5d6bedSChris Mason 
21274123bd7SChris Mason /*
21374123bd7SChris Mason  * search for key in the array p.  items p are item_size apart
21474123bd7SChris Mason  * and there are 'max' items in p
21574123bd7SChris Mason  * the slot in the array is returned via slot, and it points to
21674123bd7SChris Mason  * the place where you would insert key if it is not found in
21774123bd7SChris Mason  * the array.
21874123bd7SChris Mason  *
21974123bd7SChris Mason  * slot may point to max if the key is bigger than all of the keys
22074123bd7SChris Mason  */
2219aca1d51SChris Mason static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
222be0e5c09SChris Mason 		       int max, int *slot)
223be0e5c09SChris Mason {
224be0e5c09SChris Mason 	int low = 0;
225be0e5c09SChris Mason 	int high = max;
226be0e5c09SChris Mason 	int mid;
227be0e5c09SChris Mason 	int ret;
228e2fa7227SChris Mason 	struct btrfs_disk_key *tmp;
229be0e5c09SChris Mason 
230be0e5c09SChris Mason 	while(low < high) {
231be0e5c09SChris Mason 		mid = (low + high) / 2;
232e2fa7227SChris Mason 		tmp = (struct btrfs_disk_key *)(p + mid * item_size);
233be0e5c09SChris Mason 		ret = comp_keys(tmp, key);
234be0e5c09SChris Mason 
235be0e5c09SChris Mason 		if (ret < 0)
236be0e5c09SChris Mason 			low = mid + 1;
237be0e5c09SChris Mason 		else if (ret > 0)
238be0e5c09SChris Mason 			high = mid;
239be0e5c09SChris Mason 		else {
240be0e5c09SChris Mason 			*slot = mid;
241be0e5c09SChris Mason 			return 0;
242be0e5c09SChris Mason 		}
243be0e5c09SChris Mason 	}
244be0e5c09SChris Mason 	*slot = low;
245be0e5c09SChris Mason 	return 1;
246be0e5c09SChris Mason }
247be0e5c09SChris Mason 
24897571fd0SChris Mason /*
24997571fd0SChris Mason  * simple bin_search frontend that does the right thing for
25097571fd0SChris Mason  * leaves vs nodes
25197571fd0SChris Mason  */
2529aca1d51SChris Mason static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
253be0e5c09SChris Mason {
2547518a238SChris Mason 	if (btrfs_is_leaf(c)) {
255234b63a0SChris Mason 		struct btrfs_leaf *l = (struct btrfs_leaf *)c;
2560783fcfcSChris Mason 		return generic_bin_search((void *)l->items,
2570783fcfcSChris Mason 					  sizeof(struct btrfs_item),
2587518a238SChris Mason 					  key, btrfs_header_nritems(&c->header),
2597518a238SChris Mason 					  slot);
260be0e5c09SChris Mason 	} else {
261123abc88SChris Mason 		return generic_bin_search((void *)c->ptrs,
262123abc88SChris Mason 					  sizeof(struct btrfs_key_ptr),
2637518a238SChris Mason 					  key, btrfs_header_nritems(&c->header),
2647518a238SChris Mason 					  slot);
265be0e5c09SChris Mason 	}
266be0e5c09SChris Mason 	return -1;
267be0e5c09SChris Mason }
268be0e5c09SChris Mason 
269e20d96d6SChris Mason static struct buffer_head *read_node_slot(struct btrfs_root *root,
270e20d96d6SChris Mason 				   struct buffer_head *parent_buf,
271bb803951SChris Mason 				   int slot)
272bb803951SChris Mason {
273e20d96d6SChris Mason 	struct btrfs_node *node = btrfs_buffer_node(parent_buf);
274bb803951SChris Mason 	if (slot < 0)
275bb803951SChris Mason 		return NULL;
2767518a238SChris Mason 	if (slot >= btrfs_header_nritems(&node->header))
277bb803951SChris Mason 		return NULL;
2781d4f8a0cSChris Mason 	return read_tree_block(root, btrfs_node_blockptr(node, slot));
279bb803951SChris Mason }
280bb803951SChris Mason 
281e089f05cSChris Mason static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
282e089f05cSChris Mason 			 *root, struct btrfs_path *path, int level)
283bb803951SChris Mason {
284e20d96d6SChris Mason 	struct buffer_head *right_buf;
285e20d96d6SChris Mason 	struct buffer_head *mid_buf;
286e20d96d6SChris Mason 	struct buffer_head *left_buf;
287e20d96d6SChris Mason 	struct buffer_head *parent_buf = NULL;
288234b63a0SChris Mason 	struct btrfs_node *right = NULL;
289234b63a0SChris Mason 	struct btrfs_node *mid;
290234b63a0SChris Mason 	struct btrfs_node *left = NULL;
291234b63a0SChris Mason 	struct btrfs_node *parent = NULL;
292bb803951SChris Mason 	int ret = 0;
293bb803951SChris Mason 	int wret;
294bb803951SChris Mason 	int pslot;
295bb803951SChris Mason 	int orig_slot = path->slots[level];
29679f95c82SChris Mason 	u64 orig_ptr;
297bb803951SChris Mason 
298bb803951SChris Mason 	if (level == 0)
299bb803951SChris Mason 		return 0;
300bb803951SChris Mason 
301bb803951SChris Mason 	mid_buf = path->nodes[level];
302e20d96d6SChris Mason 	mid = btrfs_buffer_node(mid_buf);
3031d4f8a0cSChris Mason 	orig_ptr = btrfs_node_blockptr(mid, orig_slot);
30479f95c82SChris Mason 
305234b63a0SChris Mason 	if (level < BTRFS_MAX_LEVEL - 1)
306bb803951SChris Mason 		parent_buf = path->nodes[level + 1];
307bb803951SChris Mason 	pslot = path->slots[level + 1];
308bb803951SChris Mason 
30940689478SChris Mason 	/*
31040689478SChris Mason 	 * deal with the case where there is only one pointer in the root
31140689478SChris Mason 	 * by promoting the node below to a root
31240689478SChris Mason 	 */
313bb803951SChris Mason 	if (!parent_buf) {
314e20d96d6SChris Mason 		struct buffer_head *child;
3157eccb903SChris Mason 		u64 blocknr = bh_blocknr(mid_buf);
316bb803951SChris Mason 
3177518a238SChris Mason 		if (btrfs_header_nritems(&mid->header) != 1)
318bb803951SChris Mason 			return 0;
319bb803951SChris Mason 
320bb803951SChris Mason 		/* promote the child to a root */
321bb803951SChris Mason 		child = read_node_slot(root, mid_buf, 0);
322bb803951SChris Mason 		BUG_ON(!child);
323bb803951SChris Mason 		root->node = child;
324bb803951SChris Mason 		path->nodes[level] = NULL;
325d6025579SChris Mason 		clean_tree_block(trans, root, mid_buf);
326d6025579SChris Mason 		wait_on_buffer(mid_buf);
327bb803951SChris Mason 		/* once for the path */
328234b63a0SChris Mason 		btrfs_block_release(root, mid_buf);
329bb803951SChris Mason 		/* once for the root ptr */
330234b63a0SChris Mason 		btrfs_block_release(root, mid_buf);
331e089f05cSChris Mason 		return btrfs_free_extent(trans, root, blocknr, 1, 1);
332bb803951SChris Mason 	}
333e20d96d6SChris Mason 	parent = btrfs_buffer_node(parent_buf);
334bb803951SChris Mason 
335123abc88SChris Mason 	if (btrfs_header_nritems(&mid->header) >
336123abc88SChris Mason 	    BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
337bb803951SChris Mason 		return 0;
338bb803951SChris Mason 
339bb803951SChris Mason 	left_buf = read_node_slot(root, parent_buf, pslot - 1);
340bb803951SChris Mason 	right_buf = read_node_slot(root, parent_buf, pslot + 1);
34179f95c82SChris Mason 
34279f95c82SChris Mason 	/* first, try to make some room in the middle buffer */
343bb803951SChris Mason 	if (left_buf) {
344e089f05cSChris Mason 		btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1,
345e089f05cSChris Mason 				&left_buf);
346e20d96d6SChris Mason 		left = btrfs_buffer_node(left_buf);
3477518a238SChris Mason 		orig_slot += btrfs_header_nritems(&left->header);
348e089f05cSChris Mason 		wret = push_node_left(trans, root, left_buf, mid_buf);
34979f95c82SChris Mason 		if (wret < 0)
35079f95c82SChris Mason 			ret = wret;
351bb803951SChris Mason 	}
35279f95c82SChris Mason 
35379f95c82SChris Mason 	/*
35479f95c82SChris Mason 	 * then try to empty the right most buffer into the middle
35579f95c82SChris Mason 	 */
356bb803951SChris Mason 	if (right_buf) {
357e089f05cSChris Mason 		btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1,
358e089f05cSChris Mason 				&right_buf);
359e20d96d6SChris Mason 		right = btrfs_buffer_node(right_buf);
360e089f05cSChris Mason 		wret = push_node_left(trans, root, mid_buf, right_buf);
36179f95c82SChris Mason 		if (wret < 0)
36279f95c82SChris Mason 			ret = wret;
3637518a238SChris Mason 		if (btrfs_header_nritems(&right->header) == 0) {
3647eccb903SChris Mason 			u64 blocknr = bh_blocknr(right_buf);
365e089f05cSChris Mason 			clean_tree_block(trans, root, right_buf);
366d6025579SChris Mason 			wait_on_buffer(right_buf);
367d6025579SChris Mason 			btrfs_block_release(root, right_buf);
368bb803951SChris Mason 			right_buf = NULL;
369bb803951SChris Mason 			right = NULL;
370e089f05cSChris Mason 			wret = del_ptr(trans, root, path, level + 1, pslot +
371e089f05cSChris Mason 				       1);
372bb803951SChris Mason 			if (wret)
373bb803951SChris Mason 				ret = wret;
374e089f05cSChris Mason 			wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
375bb803951SChris Mason 			if (wret)
376bb803951SChris Mason 				ret = wret;
377bb803951SChris Mason 		} else {
378d6025579SChris Mason 			btrfs_memcpy(root, parent,
379d6025579SChris Mason 				     &parent->ptrs[pslot + 1].key,
380123abc88SChris Mason 				     &right->ptrs[0].key,
381e2fa7227SChris Mason 				     sizeof(struct btrfs_disk_key));
382d6025579SChris Mason 			btrfs_mark_buffer_dirty(parent_buf);
383bb803951SChris Mason 		}
384bb803951SChris Mason 	}
3857518a238SChris Mason 	if (btrfs_header_nritems(&mid->header) == 1) {
38679f95c82SChris Mason 		/*
38779f95c82SChris Mason 		 * we're not allowed to leave a node with one item in the
38879f95c82SChris Mason 		 * tree during a delete.  A deletion from lower in the tree
38979f95c82SChris Mason 		 * could try to delete the only pointer in this node.
39079f95c82SChris Mason 		 * So, pull some keys from the left.
39179f95c82SChris Mason 		 * There has to be a left pointer at this point because
39279f95c82SChris Mason 		 * otherwise we would have pulled some pointers from the
39379f95c82SChris Mason 		 * right
39479f95c82SChris Mason 		 */
39579f95c82SChris Mason 		BUG_ON(!left_buf);
396e089f05cSChris Mason 		wret = balance_node_right(trans, root, mid_buf, left_buf);
39779f95c82SChris Mason 		if (wret < 0)
39879f95c82SChris Mason 			ret = wret;
39979f95c82SChris Mason 		BUG_ON(wret == 1);
40079f95c82SChris Mason 	}
4017518a238SChris Mason 	if (btrfs_header_nritems(&mid->header) == 0) {
40279f95c82SChris Mason 		/* we've managed to empty the middle node, drop it */
4037eccb903SChris Mason 		u64 blocknr = bh_blocknr(mid_buf);
404e089f05cSChris Mason 		clean_tree_block(trans, root, mid_buf);
405d6025579SChris Mason 		wait_on_buffer(mid_buf);
406d6025579SChris Mason 		btrfs_block_release(root, mid_buf);
407bb803951SChris Mason 		mid_buf = NULL;
408bb803951SChris Mason 		mid = NULL;
409e089f05cSChris Mason 		wret = del_ptr(trans, root, path, level + 1, pslot);
410bb803951SChris Mason 		if (wret)
411bb803951SChris Mason 			ret = wret;
412e089f05cSChris Mason 		wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
413bb803951SChris Mason 		if (wret)
414bb803951SChris Mason 			ret = wret;
41579f95c82SChris Mason 	} else {
41679f95c82SChris Mason 		/* update the parent key to reflect our changes */
417d6025579SChris Mason 		btrfs_memcpy(root, parent,
418d6025579SChris Mason 			     &parent->ptrs[pslot].key, &mid->ptrs[0].key,
419e2fa7227SChris Mason 			     sizeof(struct btrfs_disk_key));
420d6025579SChris Mason 		btrfs_mark_buffer_dirty(parent_buf);
42179f95c82SChris Mason 	}
422bb803951SChris Mason 
42379f95c82SChris Mason 	/* update the path */
424bb803951SChris Mason 	if (left_buf) {
4257518a238SChris Mason 		if (btrfs_header_nritems(&left->header) > orig_slot) {
426e20d96d6SChris Mason 			get_bh(left_buf);
427bb803951SChris Mason 			path->nodes[level] = left_buf;
428bb803951SChris Mason 			path->slots[level + 1] -= 1;
429bb803951SChris Mason 			path->slots[level] = orig_slot;
430bb803951SChris Mason 			if (mid_buf)
431234b63a0SChris Mason 				btrfs_block_release(root, mid_buf);
432bb803951SChris Mason 		} else {
4337518a238SChris Mason 			orig_slot -= btrfs_header_nritems(&left->header);
434bb803951SChris Mason 			path->slots[level] = orig_slot;
435bb803951SChris Mason 		}
436bb803951SChris Mason 	}
43779f95c82SChris Mason 	/* double check we haven't messed things up */
438123abc88SChris Mason 	check_block(root, path, level);
439e20d96d6SChris Mason 	if (orig_ptr !=
440e20d96d6SChris Mason 	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
4411d4f8a0cSChris Mason 				path->slots[level]))
44279f95c82SChris Mason 		BUG();
443bb803951SChris Mason 
444bb803951SChris Mason 	if (right_buf)
445234b63a0SChris Mason 		btrfs_block_release(root, right_buf);
446bb803951SChris Mason 	if (left_buf)
447234b63a0SChris Mason 		btrfs_block_release(root, left_buf);
448bb803951SChris Mason 	return ret;
449bb803951SChris Mason }
450bb803951SChris Mason 
45174123bd7SChris Mason /*
45274123bd7SChris Mason  * look for key in the tree.  path is filled in with nodes along the way
45374123bd7SChris Mason  * if key is found, we return zero and you can find the item in the leaf
45474123bd7SChris Mason  * level of the path (level 0)
45574123bd7SChris Mason  *
45674123bd7SChris Mason  * If the key isn't found, the path points to the slot where it should
457aa5d6bedSChris Mason  * be inserted, and 1 is returned.  If there are other errors during the
458aa5d6bedSChris Mason  * search a negative error number is returned.
45997571fd0SChris Mason  *
46097571fd0SChris Mason  * if ins_len > 0, nodes and leaves will be split as we walk down the
46197571fd0SChris Mason  * tree.  if ins_len < 0, nodes will be merged as we walk down the tree (if
46297571fd0SChris Mason  * possible)
46374123bd7SChris Mason  */
464e089f05cSChris Mason int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
465e089f05cSChris Mason 		      *root, struct btrfs_key *key, struct btrfs_path *p, int
466e089f05cSChris Mason 		      ins_len, int cow)
467be0e5c09SChris Mason {
468e20d96d6SChris Mason 	struct buffer_head *b;
469e20d96d6SChris Mason 	struct buffer_head *cow_buf;
470234b63a0SChris Mason 	struct btrfs_node *c;
471be0e5c09SChris Mason 	int slot;
472be0e5c09SChris Mason 	int ret;
473be0e5c09SChris Mason 	int level;
4745c680ed6SChris Mason 
47522b0ebdaSChris Mason 	WARN_ON(p->nodes[0] != NULL);
47622b0ebdaSChris Mason 	WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
477bb803951SChris Mason again:
478bb803951SChris Mason 	b = root->node;
479e20d96d6SChris Mason 	get_bh(b);
480eb60ceacSChris Mason 	while (b) {
481e20d96d6SChris Mason 		c = btrfs_buffer_node(b);
482e20d96d6SChris Mason 		level = btrfs_header_level(&c->header);
48302217ed2SChris Mason 		if (cow) {
48402217ed2SChris Mason 			int wret;
485e20d96d6SChris Mason 			wret = btrfs_cow_block(trans, root, b,
486e20d96d6SChris Mason 					       p->nodes[level + 1],
487e20d96d6SChris Mason 					       p->slots[level + 1],
488e089f05cSChris Mason 					       &cow_buf);
48902217ed2SChris Mason 			b = cow_buf;
4902c90e5d6SChris Mason 			c = btrfs_buffer_node(b);
49102217ed2SChris Mason 		}
49202217ed2SChris Mason 		BUG_ON(!cow && ins_len);
4932c90e5d6SChris Mason 		if (level != btrfs_header_level(&c->header))
4942c90e5d6SChris Mason 			WARN_ON(1);
4952c90e5d6SChris Mason 		level = btrfs_header_level(&c->header);
496eb60ceacSChris Mason 		p->nodes[level] = b;
497123abc88SChris Mason 		ret = check_block(root, p, level);
498aa5d6bedSChris Mason 		if (ret)
499aa5d6bedSChris Mason 			return -1;
500be0e5c09SChris Mason 		ret = bin_search(c, key, &slot);
5017518a238SChris Mason 		if (!btrfs_is_leaf(c)) {
502be0e5c09SChris Mason 			if (ret && slot > 0)
503be0e5c09SChris Mason 				slot -= 1;
504be0e5c09SChris Mason 			p->slots[level] = slot;
505d4dbff95SChris Mason 			if (ins_len > 0 && btrfs_header_nritems(&c->header) >=
506d4dbff95SChris Mason 			    BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
507e089f05cSChris Mason 				int sret = split_node(trans, root, p, level);
5085c680ed6SChris Mason 				BUG_ON(sret > 0);
5095c680ed6SChris Mason 				if (sret)
5105c680ed6SChris Mason 					return sret;
5115c680ed6SChris Mason 				b = p->nodes[level];
512e20d96d6SChris Mason 				c = btrfs_buffer_node(b);
5135c680ed6SChris Mason 				slot = p->slots[level];
514bb803951SChris Mason 			} else if (ins_len < 0) {
515e089f05cSChris Mason 				int sret = balance_level(trans, root, p,
516e089f05cSChris Mason 							 level);
517bb803951SChris Mason 				if (sret)
518bb803951SChris Mason 					return sret;
519bb803951SChris Mason 				b = p->nodes[level];
520bb803951SChris Mason 				if (!b)
521bb803951SChris Mason 					goto again;
522e20d96d6SChris Mason 				c = btrfs_buffer_node(b);
523bb803951SChris Mason 				slot = p->slots[level];
5247518a238SChris Mason 				BUG_ON(btrfs_header_nritems(&c->header) == 1);
5255c680ed6SChris Mason 			}
5261d4f8a0cSChris Mason 			b = read_tree_block(root, btrfs_node_blockptr(c, slot));
527be0e5c09SChris Mason 		} else {
528234b63a0SChris Mason 			struct btrfs_leaf *l = (struct btrfs_leaf *)c;
529be0e5c09SChris Mason 			p->slots[level] = slot;
530123abc88SChris Mason 			if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
5310783fcfcSChris Mason 			    sizeof(struct btrfs_item) + ins_len) {
532d4dbff95SChris Mason 				int sret = split_leaf(trans, root, key,
533d4dbff95SChris Mason 						      p, ins_len);
5345c680ed6SChris Mason 				BUG_ON(sret > 0);
5355c680ed6SChris Mason 				if (sret)
5365c680ed6SChris Mason 					return sret;
5375c680ed6SChris Mason 			}
538be0e5c09SChris Mason 			return ret;
539be0e5c09SChris Mason 		}
540be0e5c09SChris Mason 	}
541aa5d6bedSChris Mason 	return 1;
542be0e5c09SChris Mason }
543be0e5c09SChris Mason 
54474123bd7SChris Mason /*
54574123bd7SChris Mason  * adjust the pointers going up the tree, starting at level
54674123bd7SChris Mason  * making sure the right key of each node is points to 'key'.
54774123bd7SChris Mason  * This is used after shifting pointers to the left, so it stops
54874123bd7SChris Mason  * fixing up pointers when a given leaf/node is not in slot 0 of the
54974123bd7SChris Mason  * higher levels
550aa5d6bedSChris Mason  *
551aa5d6bedSChris Mason  * If this fails to write a tree block, it returns -1, but continues
552aa5d6bedSChris Mason  * fixing up the blocks in ram so the tree is consistent.
55374123bd7SChris Mason  */
554e089f05cSChris Mason static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
555e089f05cSChris Mason 			  *root, struct btrfs_path *path, struct btrfs_disk_key
556e089f05cSChris Mason 			  *key, int level)
557be0e5c09SChris Mason {
558be0e5c09SChris Mason 	int i;
559aa5d6bedSChris Mason 	int ret = 0;
560234b63a0SChris Mason 	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
561234b63a0SChris Mason 		struct btrfs_node *t;
562be0e5c09SChris Mason 		int tslot = path->slots[i];
563eb60ceacSChris Mason 		if (!path->nodes[i])
564be0e5c09SChris Mason 			break;
565e20d96d6SChris Mason 		t = btrfs_buffer_node(path->nodes[i]);
566d6025579SChris Mason 		btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
567d6025579SChris Mason 		btrfs_mark_buffer_dirty(path->nodes[i]);
568be0e5c09SChris Mason 		if (tslot != 0)
569be0e5c09SChris Mason 			break;
570be0e5c09SChris Mason 	}
571aa5d6bedSChris Mason 	return ret;
572be0e5c09SChris Mason }
573be0e5c09SChris Mason 
57474123bd7SChris Mason /*
57574123bd7SChris Mason  * try to push data from one node into the next node left in the
57679f95c82SChris Mason  * tree.
577aa5d6bedSChris Mason  *
578aa5d6bedSChris Mason  * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
579aa5d6bedSChris Mason  * error, and > 0 if there was no room in the left hand block.
58074123bd7SChris Mason  */
581e089f05cSChris Mason static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
582e20d96d6SChris Mason 			  *root, struct buffer_head *dst_buf, struct
583e20d96d6SChris Mason 			  buffer_head *src_buf)
584be0e5c09SChris Mason {
585e20d96d6SChris Mason 	struct btrfs_node *src = btrfs_buffer_node(src_buf);
586e20d96d6SChris Mason 	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
587be0e5c09SChris Mason 	int push_items = 0;
588bb803951SChris Mason 	int src_nritems;
589bb803951SChris Mason 	int dst_nritems;
590aa5d6bedSChris Mason 	int ret = 0;
591be0e5c09SChris Mason 
5927518a238SChris Mason 	src_nritems = btrfs_header_nritems(&src->header);
5937518a238SChris Mason 	dst_nritems = btrfs_header_nritems(&dst->header);
594123abc88SChris Mason 	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
595eb60ceacSChris Mason 	if (push_items <= 0) {
596be0e5c09SChris Mason 		return 1;
597eb60ceacSChris Mason 	}
598be0e5c09SChris Mason 
599be0e5c09SChris Mason 	if (src_nritems < push_items)
600be0e5c09SChris Mason 		push_items = src_nritems;
60179f95c82SChris Mason 
602d6025579SChris Mason 	btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
603123abc88SChris Mason 		     push_items * sizeof(struct btrfs_key_ptr));
604bb803951SChris Mason 	if (push_items < src_nritems) {
605d6025579SChris Mason 		btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
606e2fa7227SChris Mason 			(src_nritems - push_items) *
607123abc88SChris Mason 			sizeof(struct btrfs_key_ptr));
608bb803951SChris Mason 	}
6097518a238SChris Mason 	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
6107518a238SChris Mason 	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
611d6025579SChris Mason 	btrfs_mark_buffer_dirty(src_buf);
612d6025579SChris Mason 	btrfs_mark_buffer_dirty(dst_buf);
613bb803951SChris Mason 	return ret;
614be0e5c09SChris Mason }
615be0e5c09SChris Mason 
61697571fd0SChris Mason /*
61779f95c82SChris Mason  * try to push data from one node into the next node right in the
61879f95c82SChris Mason  * tree.
61979f95c82SChris Mason  *
62079f95c82SChris Mason  * returns 0 if some ptrs were pushed, < 0 if there was some horrible
62179f95c82SChris Mason  * error, and > 0 if there was no room in the right hand block.
62279f95c82SChris Mason  *
62379f95c82SChris Mason  * this will  only push up to 1/2 the contents of the left node over
62479f95c82SChris Mason  */
625e089f05cSChris Mason static int balance_node_right(struct btrfs_trans_handle *trans, struct
626e20d96d6SChris Mason 			      btrfs_root *root, struct buffer_head *dst_buf,
627e20d96d6SChris Mason 			      struct buffer_head *src_buf)
62879f95c82SChris Mason {
629e20d96d6SChris Mason 	struct btrfs_node *src = btrfs_buffer_node(src_buf);
630e20d96d6SChris Mason 	struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
63179f95c82SChris Mason 	int push_items = 0;
63279f95c82SChris Mason 	int max_push;
63379f95c82SChris Mason 	int src_nritems;
63479f95c82SChris Mason 	int dst_nritems;
63579f95c82SChris Mason 	int ret = 0;
63679f95c82SChris Mason 
6377518a238SChris Mason 	src_nritems = btrfs_header_nritems(&src->header);
6387518a238SChris Mason 	dst_nritems = btrfs_header_nritems(&dst->header);
639123abc88SChris Mason 	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
64079f95c82SChris Mason 	if (push_items <= 0) {
64179f95c82SChris Mason 		return 1;
64279f95c82SChris Mason 	}
64379f95c82SChris Mason 
64479f95c82SChris Mason 	max_push = src_nritems / 2 + 1;
64579f95c82SChris Mason 	/* don't try to empty the node */
64679f95c82SChris Mason 	if (max_push > src_nritems)
64779f95c82SChris Mason 		return 1;
64879f95c82SChris Mason 	if (max_push < push_items)
64979f95c82SChris Mason 		push_items = max_push;
65079f95c82SChris Mason 
651d6025579SChris Mason 	btrfs_memmove(root, dst, dst->ptrs + push_items, dst->ptrs,
652123abc88SChris Mason 		      dst_nritems * sizeof(struct btrfs_key_ptr));
653d6025579SChris Mason 
654d6025579SChris Mason 	btrfs_memcpy(root, dst, dst->ptrs,
655d6025579SChris Mason 		     src->ptrs + src_nritems - push_items,
656123abc88SChris Mason 		     push_items * sizeof(struct btrfs_key_ptr));
65779f95c82SChris Mason 
6587518a238SChris Mason 	btrfs_set_header_nritems(&src->header, src_nritems - push_items);
6597518a238SChris Mason 	btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
66079f95c82SChris Mason 
661d6025579SChris Mason 	btrfs_mark_buffer_dirty(src_buf);
662d6025579SChris Mason 	btrfs_mark_buffer_dirty(dst_buf);
66379f95c82SChris Mason 	return ret;
66479f95c82SChris Mason }
66579f95c82SChris Mason 
66679f95c82SChris Mason /*
66797571fd0SChris Mason  * helper function to insert a new root level in the tree.
66897571fd0SChris Mason  * A new node is allocated, and a single item is inserted to
66997571fd0SChris Mason  * point to the existing root
670aa5d6bedSChris Mason  *
671aa5d6bedSChris Mason  * returns zero on success or < 0 on failure.
67297571fd0SChris Mason  */
673e089f05cSChris Mason static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
674e089f05cSChris Mason 			   *root, struct btrfs_path *path, int level)
67574123bd7SChris Mason {
676e20d96d6SChris Mason 	struct buffer_head *t;
677234b63a0SChris Mason 	struct btrfs_node *lower;
678234b63a0SChris Mason 	struct btrfs_node *c;
679e2fa7227SChris Mason 	struct btrfs_disk_key *lower_key;
6805c680ed6SChris Mason 
6815c680ed6SChris Mason 	BUG_ON(path->nodes[level]);
6825c680ed6SChris Mason 	BUG_ON(path->nodes[level-1] != root->node);
6835c680ed6SChris Mason 
684e089f05cSChris Mason 	t = btrfs_alloc_free_block(trans, root);
685e20d96d6SChris Mason 	c = btrfs_buffer_node(t);
686123abc88SChris Mason 	memset(c, 0, root->blocksize);
6877518a238SChris Mason 	btrfs_set_header_nritems(&c->header, 1);
6887518a238SChris Mason 	btrfs_set_header_level(&c->header, level);
6897eccb903SChris Mason 	btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
6907f5c1516SChris Mason 	btrfs_set_header_generation(&c->header, trans->transid);
691e20d96d6SChris Mason 	lower = btrfs_buffer_node(path->nodes[level-1]);
6923eb0314dSChris Mason 	memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
6933eb0314dSChris Mason 	       sizeof(c->header.fsid));
6947518a238SChris Mason 	if (btrfs_is_leaf(lower))
695234b63a0SChris Mason 		lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
69674123bd7SChris Mason 	else
697123abc88SChris Mason 		lower_key = &lower->ptrs[0].key;
698d6025579SChris Mason 	btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
699d6025579SChris Mason 		     sizeof(struct btrfs_disk_key));
7007eccb903SChris Mason 	btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
701d5719762SChris Mason 
702d6025579SChris Mason 	btrfs_mark_buffer_dirty(t);
703d5719762SChris Mason 
704cfaa7295SChris Mason 	/* the super has an extra ref to root->node */
705234b63a0SChris Mason 	btrfs_block_release(root, root->node);
70674123bd7SChris Mason 	root->node = t;
707e20d96d6SChris Mason 	get_bh(t);
70874123bd7SChris Mason 	path->nodes[level] = t;
70974123bd7SChris Mason 	path->slots[level] = 0;
71074123bd7SChris Mason 	return 0;
71174123bd7SChris Mason }
7125c680ed6SChris Mason 
7135c680ed6SChris Mason /*
7145c680ed6SChris Mason  * worker function to insert a single pointer in a node.
7155c680ed6SChris Mason  * the node should have enough room for the pointer already
71697571fd0SChris Mason  *
7175c680ed6SChris Mason  * slot and level indicate where you want the key to go, and
7185c680ed6SChris Mason  * blocknr is the block the key points to.
719aa5d6bedSChris Mason  *
720aa5d6bedSChris Mason  * returns zero on success and < 0 on any error
7215c680ed6SChris Mason  */
722e089f05cSChris Mason static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
723e089f05cSChris Mason 		      *root, struct btrfs_path *path, struct btrfs_disk_key
724e089f05cSChris Mason 		      *key, u64 blocknr, int slot, int level)
7255c680ed6SChris Mason {
726234b63a0SChris Mason 	struct btrfs_node *lower;
7275c680ed6SChris Mason 	int nritems;
7285c680ed6SChris Mason 
7295c680ed6SChris Mason 	BUG_ON(!path->nodes[level]);
730e20d96d6SChris Mason 	lower = btrfs_buffer_node(path->nodes[level]);
7317518a238SChris Mason 	nritems = btrfs_header_nritems(&lower->header);
73274123bd7SChris Mason 	if (slot > nritems)
73374123bd7SChris Mason 		BUG();
734123abc88SChris Mason 	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
73574123bd7SChris Mason 		BUG();
73674123bd7SChris Mason 	if (slot != nritems) {
737d6025579SChris Mason 		btrfs_memmove(root, lower, lower->ptrs + slot + 1,
738d6025579SChris Mason 			      lower->ptrs + slot,
739123abc88SChris Mason 			      (nritems - slot) * sizeof(struct btrfs_key_ptr));
74074123bd7SChris Mason 	}
741d6025579SChris Mason 	btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
742d6025579SChris Mason 		     key, sizeof(struct btrfs_disk_key));
7431d4f8a0cSChris Mason 	btrfs_set_node_blockptr(lower, slot, blocknr);
7447518a238SChris Mason 	btrfs_set_header_nritems(&lower->header, nritems + 1);
745d6025579SChris Mason 	btrfs_mark_buffer_dirty(path->nodes[level]);
74674123bd7SChris Mason 	return 0;
74774123bd7SChris Mason }
74874123bd7SChris Mason 
74997571fd0SChris Mason /*
75097571fd0SChris Mason  * split the node at the specified level in path in two.
75197571fd0SChris Mason  * The path is corrected to point to the appropriate node after the split
75297571fd0SChris Mason  *
75397571fd0SChris Mason  * Before splitting this tries to make some room in the node by pushing
75497571fd0SChris Mason  * left and right, if either one works, it returns right away.
755aa5d6bedSChris Mason  *
756aa5d6bedSChris Mason  * returns 0 on success and < 0 on failure
75797571fd0SChris Mason  */
758e089f05cSChris Mason static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
759e089f05cSChris Mason 		      *root, struct btrfs_path *path, int level)
760be0e5c09SChris Mason {
761e20d96d6SChris Mason 	struct buffer_head *t;
762234b63a0SChris Mason 	struct btrfs_node *c;
763e20d96d6SChris Mason 	struct buffer_head *split_buffer;
764234b63a0SChris Mason 	struct btrfs_node *split;
765be0e5c09SChris Mason 	int mid;
7665c680ed6SChris Mason 	int ret;
767aa5d6bedSChris Mason 	int wret;
7687518a238SChris Mason 	u32 c_nritems;
769be0e5c09SChris Mason 
7705c680ed6SChris Mason 	t = path->nodes[level];
771e20d96d6SChris Mason 	c = btrfs_buffer_node(t);
7725c680ed6SChris Mason 	if (t == root->node) {
7735c680ed6SChris Mason 		/* trying to split the root, lets make a new one */
774e089f05cSChris Mason 		ret = insert_new_root(trans, root, path, level + 1);
7755c680ed6SChris Mason 		if (ret)
7765c680ed6SChris Mason 			return ret;
7775c680ed6SChris Mason 	}
7787518a238SChris Mason 	c_nritems = btrfs_header_nritems(&c->header);
779e089f05cSChris Mason 	split_buffer = btrfs_alloc_free_block(trans, root);
780e20d96d6SChris Mason 	split = btrfs_buffer_node(split_buffer);
7817518a238SChris Mason 	btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
7829a6f11edSChris Mason 	btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
7837eccb903SChris Mason 	btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer));
7847f5c1516SChris Mason 	btrfs_set_header_generation(&split->header, trans->transid);
7853eb0314dSChris Mason 	memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
7863eb0314dSChris Mason 	       sizeof(split->header.fsid));
7877518a238SChris Mason 	mid = (c_nritems + 1) / 2;
788d6025579SChris Mason 	btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
789123abc88SChris Mason 		     (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
7907518a238SChris Mason 	btrfs_set_header_nritems(&split->header, c_nritems - mid);
7917518a238SChris Mason 	btrfs_set_header_nritems(&c->header, mid);
792aa5d6bedSChris Mason 	ret = 0;
793aa5d6bedSChris Mason 
794d6025579SChris Mason 	btrfs_mark_buffer_dirty(t);
795d6025579SChris Mason 	btrfs_mark_buffer_dirty(split_buffer);
796e089f05cSChris Mason 	wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
7977eccb903SChris Mason 			  bh_blocknr(split_buffer), path->slots[level + 1] + 1,
798123abc88SChris Mason 			  level + 1);
799aa5d6bedSChris Mason 	if (wret)
800aa5d6bedSChris Mason 		ret = wret;
801aa5d6bedSChris Mason 
8025de08d7dSChris Mason 	if (path->slots[level] >= mid) {
8035c680ed6SChris Mason 		path->slots[level] -= mid;
804234b63a0SChris Mason 		btrfs_block_release(root, t);
8055c680ed6SChris Mason 		path->nodes[level] = split_buffer;
8065c680ed6SChris Mason 		path->slots[level + 1] += 1;
807eb60ceacSChris Mason 	} else {
808234b63a0SChris Mason 		btrfs_block_release(root, split_buffer);
809be0e5c09SChris Mason 	}
810aa5d6bedSChris Mason 	return ret;
811be0e5c09SChris Mason }
812be0e5c09SChris Mason 
81374123bd7SChris Mason /*
81474123bd7SChris Mason  * how many bytes are required to store the items in a leaf.  start
81574123bd7SChris Mason  * and nr indicate which items in the leaf to check.  This totals up the
81674123bd7SChris Mason  * space used both by the item structs and the item data
81774123bd7SChris Mason  */
818234b63a0SChris Mason static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
819be0e5c09SChris Mason {
820be0e5c09SChris Mason 	int data_len;
821d4dbff95SChris Mason 	int nritems = btrfs_header_nritems(&l->header);
822d4dbff95SChris Mason 	int end = min(nritems, start + nr) - 1;
823be0e5c09SChris Mason 
824be0e5c09SChris Mason 	if (!nr)
825be0e5c09SChris Mason 		return 0;
8260783fcfcSChris Mason 	data_len = btrfs_item_end(l->items + start);
8270783fcfcSChris Mason 	data_len = data_len - btrfs_item_offset(l->items + end);
8280783fcfcSChris Mason 	data_len += sizeof(struct btrfs_item) * nr;
829d4dbff95SChris Mason 	WARN_ON(data_len < 0);
830be0e5c09SChris Mason 	return data_len;
831be0e5c09SChris Mason }
832be0e5c09SChris Mason 
83374123bd7SChris Mason /*
834d4dbff95SChris Mason  * The space between the end of the leaf items and
835d4dbff95SChris Mason  * the start of the leaf data.  IOW, how much room
836d4dbff95SChris Mason  * the leaf has left for both items and data
837d4dbff95SChris Mason  */
838d4dbff95SChris Mason int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf)
839d4dbff95SChris Mason {
840d4dbff95SChris Mason 	int nritems = btrfs_header_nritems(&leaf->header);
841d4dbff95SChris Mason 	return BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
842d4dbff95SChris Mason }
843d4dbff95SChris Mason 
844d4dbff95SChris Mason /*
84500ec4c51SChris Mason  * push some data in the path leaf to the right, trying to free up at
84600ec4c51SChris Mason  * least data_size bytes.  returns zero if the push worked, nonzero otherwise
847aa5d6bedSChris Mason  *
848aa5d6bedSChris Mason  * returns 1 if the push failed because the other node didn't have enough
849aa5d6bedSChris Mason  * room, 0 if everything worked out and < 0 if there were major errors.
85000ec4c51SChris Mason  */
851e089f05cSChris Mason static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
852e089f05cSChris Mason 			   *root, struct btrfs_path *path, int data_size)
85300ec4c51SChris Mason {
854e20d96d6SChris Mason 	struct buffer_head *left_buf = path->nodes[0];
855e20d96d6SChris Mason 	struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
856234b63a0SChris Mason 	struct btrfs_leaf *right;
857e20d96d6SChris Mason 	struct buffer_head *right_buf;
858e20d96d6SChris Mason 	struct buffer_head *upper;
859e20d96d6SChris Mason 	struct btrfs_node *upper_node;
86000ec4c51SChris Mason 	int slot;
86100ec4c51SChris Mason 	int i;
86200ec4c51SChris Mason 	int free_space;
86300ec4c51SChris Mason 	int push_space = 0;
86400ec4c51SChris Mason 	int push_items = 0;
8650783fcfcSChris Mason 	struct btrfs_item *item;
8667518a238SChris Mason 	u32 left_nritems;
8677518a238SChris Mason 	u32 right_nritems;
86800ec4c51SChris Mason 
86900ec4c51SChris Mason 	slot = path->slots[1];
87000ec4c51SChris Mason 	if (!path->nodes[1]) {
87100ec4c51SChris Mason 		return 1;
87200ec4c51SChris Mason 	}
87300ec4c51SChris Mason 	upper = path->nodes[1];
874e20d96d6SChris Mason 	upper_node = btrfs_buffer_node(upper);
875e20d96d6SChris Mason 	if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
87600ec4c51SChris Mason 		return 1;
87700ec4c51SChris Mason 	}
878e20d96d6SChris Mason 	right_buf = read_tree_block(root,
879e20d96d6SChris Mason 		    btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
880e20d96d6SChris Mason 	right = btrfs_buffer_leaf(right_buf);
881123abc88SChris Mason 	free_space = btrfs_leaf_free_space(root, right);
8820783fcfcSChris Mason 	if (free_space < data_size + sizeof(struct btrfs_item)) {
883234b63a0SChris Mason 		btrfs_block_release(root, right_buf);
88400ec4c51SChris Mason 		return 1;
88500ec4c51SChris Mason 	}
88602217ed2SChris Mason 	/* cow and double check */
887e089f05cSChris Mason 	btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf);
888e20d96d6SChris Mason 	right = btrfs_buffer_leaf(right_buf);
889123abc88SChris Mason 	free_space = btrfs_leaf_free_space(root, right);
8900783fcfcSChris Mason 	if (free_space < data_size + sizeof(struct btrfs_item)) {
891234b63a0SChris Mason 		btrfs_block_release(root, right_buf);
89202217ed2SChris Mason 		return 1;
89302217ed2SChris Mason 	}
89402217ed2SChris Mason 
8957518a238SChris Mason 	left_nritems = btrfs_header_nritems(&left->header);
8967518a238SChris Mason 	for (i = left_nritems - 1; i >= 0; i--) {
89700ec4c51SChris Mason 		item = left->items + i;
89800ec4c51SChris Mason 		if (path->slots[0] == i)
89900ec4c51SChris Mason 			push_space += data_size + sizeof(*item);
9000783fcfcSChris Mason 		if (btrfs_item_size(item) + sizeof(*item) + push_space >
9010783fcfcSChris Mason 		    free_space)
90200ec4c51SChris Mason 			break;
90300ec4c51SChris Mason 		push_items++;
9040783fcfcSChris Mason 		push_space += btrfs_item_size(item) + sizeof(*item);
90500ec4c51SChris Mason 	}
90600ec4c51SChris Mason 	if (push_items == 0) {
907234b63a0SChris Mason 		btrfs_block_release(root, right_buf);
90800ec4c51SChris Mason 		return 1;
90900ec4c51SChris Mason 	}
9107518a238SChris Mason 	right_nritems = btrfs_header_nritems(&right->header);
91100ec4c51SChris Mason 	/* push left to right */
9120783fcfcSChris Mason 	push_space = btrfs_item_end(left->items + left_nritems - push_items);
913123abc88SChris Mason 	push_space -= leaf_data_end(root, left);
91400ec4c51SChris Mason 	/* make room in the right data area */
915d6025579SChris Mason 	btrfs_memmove(root, right, btrfs_leaf_data(right) +
916d6025579SChris Mason 		      leaf_data_end(root, right) - push_space,
917d6025579SChris Mason 		      btrfs_leaf_data(right) +
918d6025579SChris Mason 		      leaf_data_end(root, right), BTRFS_LEAF_DATA_SIZE(root) -
919d6025579SChris Mason 		      leaf_data_end(root, right));
92000ec4c51SChris Mason 	/* copy from the left data area */
921d6025579SChris Mason 	btrfs_memcpy(root, right, btrfs_leaf_data(right) +
922d6025579SChris Mason 		     BTRFS_LEAF_DATA_SIZE(root) - push_space,
923d6025579SChris Mason 		     btrfs_leaf_data(left) + leaf_data_end(root, left),
924d6025579SChris Mason 		     push_space);
925d6025579SChris Mason 	btrfs_memmove(root, right, right->items + push_items, right->items,
9260783fcfcSChris Mason 		right_nritems * sizeof(struct btrfs_item));
92700ec4c51SChris Mason 	/* copy the items from left to right */
928d6025579SChris Mason 	btrfs_memcpy(root, right, right->items, left->items +
929d6025579SChris Mason 		     left_nritems - push_items,
9300783fcfcSChris Mason 		     push_items * sizeof(struct btrfs_item));
93100ec4c51SChris Mason 
93200ec4c51SChris Mason 	/* update the item pointers */
9337518a238SChris Mason 	right_nritems += push_items;
9347518a238SChris Mason 	btrfs_set_header_nritems(&right->header, right_nritems);
935123abc88SChris Mason 	push_space = BTRFS_LEAF_DATA_SIZE(root);
9367518a238SChris Mason 	for (i = 0; i < right_nritems; i++) {
9370783fcfcSChris Mason 		btrfs_set_item_offset(right->items + i, push_space -
9380783fcfcSChris Mason 				      btrfs_item_size(right->items + i));
9390783fcfcSChris Mason 		push_space = btrfs_item_offset(right->items + i);
94000ec4c51SChris Mason 	}
9417518a238SChris Mason 	left_nritems -= push_items;
9427518a238SChris Mason 	btrfs_set_header_nritems(&left->header, left_nritems);
94300ec4c51SChris Mason 
944d6025579SChris Mason 	btrfs_mark_buffer_dirty(left_buf);
945d6025579SChris Mason 	btrfs_mark_buffer_dirty(right_buf);
946d6025579SChris Mason 	btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key,
947e2fa7227SChris Mason 		&right->items[0].key, sizeof(struct btrfs_disk_key));
948d6025579SChris Mason 	btrfs_mark_buffer_dirty(upper);
94902217ed2SChris Mason 
95000ec4c51SChris Mason 	/* then fixup the leaf pointer in the path */
9517518a238SChris Mason 	if (path->slots[0] >= left_nritems) {
9527518a238SChris Mason 		path->slots[0] -= left_nritems;
953234b63a0SChris Mason 		btrfs_block_release(root, path->nodes[0]);
95400ec4c51SChris Mason 		path->nodes[0] = right_buf;
95500ec4c51SChris Mason 		path->slots[1] += 1;
95600ec4c51SChris Mason 	} else {
957234b63a0SChris Mason 		btrfs_block_release(root, right_buf);
95800ec4c51SChris Mason 	}
95900ec4c51SChris Mason 	return 0;
96000ec4c51SChris Mason }
96100ec4c51SChris Mason /*
96274123bd7SChris Mason  * push some data in the path leaf to the left, trying to free up at
96374123bd7SChris Mason  * least data_size bytes.  returns zero if the push worked, nonzero otherwise
96474123bd7SChris Mason  */
965e089f05cSChris Mason static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
966e089f05cSChris Mason 			  *root, struct btrfs_path *path, int data_size)
967be0e5c09SChris Mason {
968e20d96d6SChris Mason 	struct buffer_head *right_buf = path->nodes[0];
969e20d96d6SChris Mason 	struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
970e20d96d6SChris Mason 	struct buffer_head *t;
971234b63a0SChris Mason 	struct btrfs_leaf *left;
972be0e5c09SChris Mason 	int slot;
973be0e5c09SChris Mason 	int i;
974be0e5c09SChris Mason 	int free_space;
975be0e5c09SChris Mason 	int push_space = 0;
976be0e5c09SChris Mason 	int push_items = 0;
9770783fcfcSChris Mason 	struct btrfs_item *item;
9787518a238SChris Mason 	u32 old_left_nritems;
979aa5d6bedSChris Mason 	int ret = 0;
980aa5d6bedSChris Mason 	int wret;
981be0e5c09SChris Mason 
982be0e5c09SChris Mason 	slot = path->slots[1];
983be0e5c09SChris Mason 	if (slot == 0) {
984be0e5c09SChris Mason 		return 1;
985be0e5c09SChris Mason 	}
986be0e5c09SChris Mason 	if (!path->nodes[1]) {
987be0e5c09SChris Mason 		return 1;
988be0e5c09SChris Mason 	}
989e20d96d6SChris Mason 	t = read_tree_block(root,
990e20d96d6SChris Mason 	    btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
991e20d96d6SChris Mason 	left = btrfs_buffer_leaf(t);
992123abc88SChris Mason 	free_space = btrfs_leaf_free_space(root, left);
9930783fcfcSChris Mason 	if (free_space < data_size + sizeof(struct btrfs_item)) {
994234b63a0SChris Mason 		btrfs_block_release(root, t);
995be0e5c09SChris Mason 		return 1;
996be0e5c09SChris Mason 	}
99702217ed2SChris Mason 
99802217ed2SChris Mason 	/* cow and double check */
999e089f05cSChris Mason 	btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
1000e20d96d6SChris Mason 	left = btrfs_buffer_leaf(t);
1001123abc88SChris Mason 	free_space = btrfs_leaf_free_space(root, left);
10020783fcfcSChris Mason 	if (free_space < data_size + sizeof(struct btrfs_item)) {
1003234b63a0SChris Mason 		btrfs_block_release(root, t);
100402217ed2SChris Mason 		return 1;
100502217ed2SChris Mason 	}
100602217ed2SChris Mason 
10077518a238SChris Mason 	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
1008be0e5c09SChris Mason 		item = right->items + i;
1009be0e5c09SChris Mason 		if (path->slots[0] == i)
1010be0e5c09SChris Mason 			push_space += data_size + sizeof(*item);
10110783fcfcSChris Mason 		if (btrfs_item_size(item) + sizeof(*item) + push_space >
10120783fcfcSChris Mason 		    free_space)
1013be0e5c09SChris Mason 			break;
1014be0e5c09SChris Mason 		push_items++;
10150783fcfcSChris Mason 		push_space += btrfs_item_size(item) + sizeof(*item);
1016be0e5c09SChris Mason 	}
1017be0e5c09SChris Mason 	if (push_items == 0) {
1018234b63a0SChris Mason 		btrfs_block_release(root, t);
1019be0e5c09SChris Mason 		return 1;
1020be0e5c09SChris Mason 	}
1021be0e5c09SChris Mason 	/* push data from right to left */
1022d6025579SChris Mason 	btrfs_memcpy(root, left, left->items +
1023d6025579SChris Mason 		     btrfs_header_nritems(&left->header),
10240783fcfcSChris Mason 		     right->items, push_items * sizeof(struct btrfs_item));
1025123abc88SChris Mason 	push_space = BTRFS_LEAF_DATA_SIZE(root) -
10260783fcfcSChris Mason 		     btrfs_item_offset(right->items + push_items -1);
1027d6025579SChris Mason 	btrfs_memcpy(root, left, btrfs_leaf_data(left) +
1028d6025579SChris Mason 		     leaf_data_end(root, left) - push_space,
1029123abc88SChris Mason 		     btrfs_leaf_data(right) +
1030123abc88SChris Mason 		     btrfs_item_offset(right->items + push_items - 1),
1031be0e5c09SChris Mason 		     push_space);
10327518a238SChris Mason 	old_left_nritems = btrfs_header_nritems(&left->header);
1033eb60ceacSChris Mason 	BUG_ON(old_left_nritems < 0);
1034eb60ceacSChris Mason 
1035be0e5c09SChris Mason 	for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
1036123abc88SChris Mason 		u32 ioff = btrfs_item_offset(left->items + i);
1037123abc88SChris Mason 		btrfs_set_item_offset(left->items + i, ioff -
1038123abc88SChris Mason 				     (BTRFS_LEAF_DATA_SIZE(root) -
10390783fcfcSChris Mason 				      btrfs_item_offset(left->items +
10400783fcfcSChris Mason 						        old_left_nritems - 1)));
1041be0e5c09SChris Mason 	}
10427518a238SChris Mason 	btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
1043be0e5c09SChris Mason 
1044be0e5c09SChris Mason 	/* fixup right node */
10450783fcfcSChris Mason 	push_space = btrfs_item_offset(right->items + push_items - 1) -
1046123abc88SChris Mason 		     leaf_data_end(root, right);
1047d6025579SChris Mason 	btrfs_memmove(root, right, btrfs_leaf_data(right) +
1048d6025579SChris Mason 		      BTRFS_LEAF_DATA_SIZE(root) - push_space,
1049d6025579SChris Mason 		      btrfs_leaf_data(right) +
1050123abc88SChris Mason 		      leaf_data_end(root, right), push_space);
1051d6025579SChris Mason 	btrfs_memmove(root, right, right->items, right->items + push_items,
10527518a238SChris Mason 		(btrfs_header_nritems(&right->header) - push_items) *
10530783fcfcSChris Mason 		sizeof(struct btrfs_item));
10547518a238SChris Mason 	btrfs_set_header_nritems(&right->header,
10557518a238SChris Mason 				 btrfs_header_nritems(&right->header) -
10567518a238SChris Mason 				 push_items);
1057123abc88SChris Mason 	push_space = BTRFS_LEAF_DATA_SIZE(root);
1058eb60ceacSChris Mason 
10597518a238SChris Mason 	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
10600783fcfcSChris Mason 		btrfs_set_item_offset(right->items + i, push_space -
10610783fcfcSChris Mason 				      btrfs_item_size(right->items + i));
10620783fcfcSChris Mason 		push_space = btrfs_item_offset(right->items + i);
1063be0e5c09SChris Mason 	}
1064eb60ceacSChris Mason 
1065d6025579SChris Mason 	btrfs_mark_buffer_dirty(t);
1066d6025579SChris Mason 	btrfs_mark_buffer_dirty(right_buf);
1067eb60ceacSChris Mason 
1068e089f05cSChris Mason 	wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
1069aa5d6bedSChris Mason 	if (wret)
1070aa5d6bedSChris Mason 		ret = wret;
1071be0e5c09SChris Mason 
1072be0e5c09SChris Mason 	/* then fixup the leaf pointer in the path */
1073be0e5c09SChris Mason 	if (path->slots[0] < push_items) {
1074be0e5c09SChris Mason 		path->slots[0] += old_left_nritems;
1075234b63a0SChris Mason 		btrfs_block_release(root, path->nodes[0]);
1076eb60ceacSChris Mason 		path->nodes[0] = t;
1077be0e5c09SChris Mason 		path->slots[1] -= 1;
1078be0e5c09SChris Mason 	} else {
1079234b63a0SChris Mason 		btrfs_block_release(root, t);
1080be0e5c09SChris Mason 		path->slots[0] -= push_items;
1081be0e5c09SChris Mason 	}
1082eb60ceacSChris Mason 	BUG_ON(path->slots[0] < 0);
1083aa5d6bedSChris Mason 	return ret;
1084be0e5c09SChris Mason }
1085be0e5c09SChris Mason 
108674123bd7SChris Mason /*
108774123bd7SChris Mason  * split the path's leaf in two, making sure there is at least data_size
108874123bd7SChris Mason  * available for the resulting leaf level of the path.
1089aa5d6bedSChris Mason  *
1090aa5d6bedSChris Mason  * returns 0 if all went well and < 0 on failure.
109174123bd7SChris Mason  */
1092e089f05cSChris Mason static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1093d4dbff95SChris Mason 		      *root, struct btrfs_key *ins_key,
1094d4dbff95SChris Mason 		      struct btrfs_path *path, int data_size)
1095be0e5c09SChris Mason {
1096e20d96d6SChris Mason 	struct buffer_head *l_buf;
1097234b63a0SChris Mason 	struct btrfs_leaf *l;
10987518a238SChris Mason 	u32 nritems;
1099eb60ceacSChris Mason 	int mid;
1100eb60ceacSChris Mason 	int slot;
1101234b63a0SChris Mason 	struct btrfs_leaf *right;
1102e20d96d6SChris Mason 	struct buffer_head *right_buffer;
11030783fcfcSChris Mason 	int space_needed = data_size + sizeof(struct btrfs_item);
1104be0e5c09SChris Mason 	int data_copy_size;
1105be0e5c09SChris Mason 	int rt_data_off;
1106be0e5c09SChris Mason 	int i;
1107d4dbff95SChris Mason 	int ret = 0;
1108aa5d6bedSChris Mason 	int wret;
1109d4dbff95SChris Mason 	int double_split = 0;
1110d4dbff95SChris Mason 	struct btrfs_disk_key disk_key;
1111be0e5c09SChris Mason 
111240689478SChris Mason 	/* first try to make some room by pushing left and right */
1113e089f05cSChris Mason 	wret = push_leaf_left(trans, root, path, data_size);
1114eaee50e8SChris Mason 	if (wret < 0)
1115eaee50e8SChris Mason 		return wret;
1116eaee50e8SChris Mason 	if (wret) {
1117e089f05cSChris Mason 		wret = push_leaf_right(trans, root, path, data_size);
1118eaee50e8SChris Mason 		if (wret < 0)
1119eaee50e8SChris Mason 			return wret;
1120eaee50e8SChris Mason 	}
1121eb60ceacSChris Mason 	l_buf = path->nodes[0];
1122e20d96d6SChris Mason 	l = btrfs_buffer_leaf(l_buf);
1123aa5d6bedSChris Mason 
1124aa5d6bedSChris Mason 	/* did the pushes work? */
1125123abc88SChris Mason 	if (btrfs_leaf_free_space(root, l) >=
1126123abc88SChris Mason 	    sizeof(struct btrfs_item) + data_size)
1127be0e5c09SChris Mason 		return 0;
1128aa5d6bedSChris Mason 
11295c680ed6SChris Mason 	if (!path->nodes[1]) {
1130e089f05cSChris Mason 		ret = insert_new_root(trans, root, path, 1);
11315c680ed6SChris Mason 		if (ret)
11325c680ed6SChris Mason 			return ret;
11335c680ed6SChris Mason 	}
1134eb60ceacSChris Mason 	slot = path->slots[0];
11357518a238SChris Mason 	nritems = btrfs_header_nritems(&l->header);
1136eb60ceacSChris Mason 	mid = (nritems + 1)/ 2;
1137e089f05cSChris Mason 	right_buffer = btrfs_alloc_free_block(trans, root);
1138eb60ceacSChris Mason 	BUG_ON(!right_buffer);
1139e20d96d6SChris Mason 	right = btrfs_buffer_leaf(right_buffer);
1140123abc88SChris Mason 	memset(&right->header, 0, sizeof(right->header));
11417eccb903SChris Mason 	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
11427f5c1516SChris Mason 	btrfs_set_header_generation(&right->header, trans->transid);
11437518a238SChris Mason 	btrfs_set_header_level(&right->header, 0);
11443eb0314dSChris Mason 	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
11453eb0314dSChris Mason 	       sizeof(right->header.fsid));
1146d4dbff95SChris Mason 	if (mid <= slot) {
1147d4dbff95SChris Mason 		if (nritems == 1 ||
1148d4dbff95SChris Mason 		    leaf_space_used(l, mid, nritems - mid) + space_needed >
1149d4dbff95SChris Mason 			BTRFS_LEAF_DATA_SIZE(root)) {
1150d4dbff95SChris Mason 			if (slot >= nritems) {
1151d4dbff95SChris Mason 				btrfs_cpu_key_to_disk(&disk_key, ins_key);
1152d4dbff95SChris Mason 				btrfs_set_header_nritems(&right->header, 0);
1153d4dbff95SChris Mason 				wret = insert_ptr(trans, root, path,
1154d4dbff95SChris Mason 						  &disk_key,
11557eccb903SChris Mason 						  bh_blocknr(right_buffer),
1156d4dbff95SChris Mason 						  path->slots[1] + 1, 1);
1157d4dbff95SChris Mason 				if (wret)
1158d4dbff95SChris Mason 					ret = wret;
1159d4dbff95SChris Mason 				btrfs_block_release(root, path->nodes[0]);
1160d4dbff95SChris Mason 				path->nodes[0] = right_buffer;
1161d4dbff95SChris Mason 				path->slots[0] = 0;
1162d4dbff95SChris Mason 				path->slots[1] += 1;
1163d4dbff95SChris Mason 				return ret;
1164d4dbff95SChris Mason 			}
1165d4dbff95SChris Mason 			mid = slot;
1166d4dbff95SChris Mason 			double_split = 1;
1167d4dbff95SChris Mason 		}
1168d4dbff95SChris Mason 	} else {
1169d4dbff95SChris Mason 		if (leaf_space_used(l, 0, mid + 1) + space_needed >
1170d4dbff95SChris Mason 			BTRFS_LEAF_DATA_SIZE(root)) {
1171d4dbff95SChris Mason 			if (slot == 0) {
1172d4dbff95SChris Mason 				btrfs_cpu_key_to_disk(&disk_key, ins_key);
1173d4dbff95SChris Mason 				btrfs_set_header_nritems(&right->header, 0);
1174d4dbff95SChris Mason 				wret = insert_ptr(trans, root, path,
1175d4dbff95SChris Mason 						  &disk_key,
11767eccb903SChris Mason 						  bh_blocknr(right_buffer),
1177d4dbff95SChris Mason 						  path->slots[1] - 1, 1);
1178d4dbff95SChris Mason 				if (wret)
1179d4dbff95SChris Mason 					ret = wret;
1180d4dbff95SChris Mason 				btrfs_block_release(root, path->nodes[0]);
1181d4dbff95SChris Mason 				path->nodes[0] = right_buffer;
1182d4dbff95SChris Mason 				path->slots[0] = 0;
1183d4dbff95SChris Mason 				path->slots[1] -= 1;
1184d4dbff95SChris Mason 				return ret;
1185d4dbff95SChris Mason 			}
1186d4dbff95SChris Mason 			mid = slot;
1187d4dbff95SChris Mason 			double_split = 1;
1188d4dbff95SChris Mason 		}
1189d4dbff95SChris Mason 	}
1190d4dbff95SChris Mason 	btrfs_set_header_nritems(&right->header, nritems - mid);
1191123abc88SChris Mason 	data_copy_size = btrfs_item_end(l->items + mid) -
1192123abc88SChris Mason 			 leaf_data_end(root, l);
1193d6025579SChris Mason 	btrfs_memcpy(root, right, right->items, l->items + mid,
11940783fcfcSChris Mason 		     (nritems - mid) * sizeof(struct btrfs_item));
1195d6025579SChris Mason 	btrfs_memcpy(root, right,
1196d6025579SChris Mason 		     btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) -
1197123abc88SChris Mason 		     data_copy_size, btrfs_leaf_data(l) +
1198123abc88SChris Mason 		     leaf_data_end(root, l), data_copy_size);
1199123abc88SChris Mason 	rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
1200123abc88SChris Mason 		      btrfs_item_end(l->items + mid);
120174123bd7SChris Mason 
12020783fcfcSChris Mason 	for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
1203123abc88SChris Mason 		u32 ioff = btrfs_item_offset(right->items + i);
12040783fcfcSChris Mason 		btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
12050783fcfcSChris Mason 	}
120674123bd7SChris Mason 
12077518a238SChris Mason 	btrfs_set_header_nritems(&l->header, mid);
1208aa5d6bedSChris Mason 	ret = 0;
1209e089f05cSChris Mason 	wret = insert_ptr(trans, root, path, &right->items[0].key,
12107eccb903SChris Mason 			  bh_blocknr(right_buffer), path->slots[1] + 1, 1);
1211aa5d6bedSChris Mason 	if (wret)
1212aa5d6bedSChris Mason 		ret = wret;
1213d6025579SChris Mason 	btrfs_mark_buffer_dirty(right_buffer);
1214d6025579SChris Mason 	btrfs_mark_buffer_dirty(l_buf);
1215eb60ceacSChris Mason 	BUG_ON(path->slots[0] != slot);
1216be0e5c09SChris Mason 	if (mid <= slot) {
1217234b63a0SChris Mason 		btrfs_block_release(root, path->nodes[0]);
1218eb60ceacSChris Mason 		path->nodes[0] = right_buffer;
1219be0e5c09SChris Mason 		path->slots[0] -= mid;
1220be0e5c09SChris Mason 		path->slots[1] += 1;
1221eb60ceacSChris Mason 	} else
1222234b63a0SChris Mason 		btrfs_block_release(root, right_buffer);
1223eb60ceacSChris Mason 	BUG_ON(path->slots[0] < 0);
1224d4dbff95SChris Mason 
1225d4dbff95SChris Mason 	if (!double_split)
1226d4dbff95SChris Mason 		return ret;
1227d4dbff95SChris Mason 	right_buffer = btrfs_alloc_free_block(trans, root);
1228d4dbff95SChris Mason 	BUG_ON(!right_buffer);
1229d4dbff95SChris Mason 	right = btrfs_buffer_leaf(right_buffer);
1230d4dbff95SChris Mason 	memset(&right->header, 0, sizeof(right->header));
12317eccb903SChris Mason 	btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
1232d4dbff95SChris Mason 	btrfs_set_header_generation(&right->header, trans->transid);
1233d4dbff95SChris Mason 	btrfs_set_header_level(&right->header, 0);
12343eb0314dSChris Mason 	memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
12353eb0314dSChris Mason 	       sizeof(right->header.fsid));
1236d4dbff95SChris Mason 	btrfs_cpu_key_to_disk(&disk_key, ins_key);
1237d4dbff95SChris Mason 	btrfs_set_header_nritems(&right->header, 0);
1238d4dbff95SChris Mason 	wret = insert_ptr(trans, root, path,
1239d4dbff95SChris Mason 			  &disk_key,
12407eccb903SChris Mason 			  bh_blocknr(right_buffer),
1241d4dbff95SChris Mason 			  path->slots[1], 1);
1242d4dbff95SChris Mason 	if (wret)
1243d4dbff95SChris Mason 		ret = wret;
1244d4dbff95SChris Mason 	btrfs_block_release(root, path->nodes[0]);
1245d4dbff95SChris Mason 	path->nodes[0] = right_buffer;
1246d4dbff95SChris Mason 	path->slots[0] = 0;
1247d4dbff95SChris Mason 	check_node(root, path, 1);
1248d4dbff95SChris Mason 	check_leaf(root, path, 0);
1249be0e5c09SChris Mason 	return ret;
1250be0e5c09SChris Mason }
1251be0e5c09SChris Mason 
1252b18c6685SChris Mason int btrfs_truncate_item(struct btrfs_trans_handle *trans,
1253b18c6685SChris Mason 			struct btrfs_root *root,
1254b18c6685SChris Mason 			struct btrfs_path *path,
1255b18c6685SChris Mason 			u32 new_size)
1256b18c6685SChris Mason {
1257b18c6685SChris Mason 	int ret = 0;
1258b18c6685SChris Mason 	int slot;
1259b18c6685SChris Mason 	int slot_orig;
1260b18c6685SChris Mason 	struct btrfs_leaf *leaf;
1261b18c6685SChris Mason 	struct buffer_head *leaf_buf;
1262b18c6685SChris Mason 	u32 nritems;
1263b18c6685SChris Mason 	unsigned int data_end;
1264b18c6685SChris Mason 	unsigned int old_data_start;
1265b18c6685SChris Mason 	unsigned int old_size;
1266b18c6685SChris Mason 	unsigned int size_diff;
1267b18c6685SChris Mason 	int i;
1268b18c6685SChris Mason 
1269b18c6685SChris Mason 	slot_orig = path->slots[0];
1270b18c6685SChris Mason 	leaf_buf = path->nodes[0];
1271b18c6685SChris Mason 	leaf = btrfs_buffer_leaf(leaf_buf);
1272b18c6685SChris Mason 
1273b18c6685SChris Mason 	nritems = btrfs_header_nritems(&leaf->header);
1274b18c6685SChris Mason 	data_end = leaf_data_end(root, leaf);
1275b18c6685SChris Mason 
1276b18c6685SChris Mason 	slot = path->slots[0];
1277b18c6685SChris Mason 	old_data_start = btrfs_item_offset(leaf->items + slot);
1278b18c6685SChris Mason 	old_size = btrfs_item_size(leaf->items + slot);
1279b18c6685SChris Mason 	BUG_ON(old_size <= new_size);
1280b18c6685SChris Mason 	size_diff = old_size - new_size;
1281b18c6685SChris Mason 
1282b18c6685SChris Mason 	BUG_ON(slot < 0);
1283b18c6685SChris Mason 	BUG_ON(slot >= nritems);
1284b18c6685SChris Mason 
1285b18c6685SChris Mason 	/*
1286b18c6685SChris Mason 	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1287b18c6685SChris Mason 	 */
1288b18c6685SChris Mason 	/* first correct the data pointers */
1289b18c6685SChris Mason 	for (i = slot; i < nritems; i++) {
1290b18c6685SChris Mason 		u32 ioff = btrfs_item_offset(leaf->items + i);
1291b18c6685SChris Mason 		btrfs_set_item_offset(leaf->items + i,
1292b18c6685SChris Mason 				      ioff + size_diff);
1293b18c6685SChris Mason 	}
1294b18c6685SChris Mason 	/* shift the data */
1295b18c6685SChris Mason printk("truncate item, new_size %u old_size %u, diff %u, bufp %p, dst, %p, num %u, old_data_start %u, data_end %u\n", new_size, old_size, size_diff, leaf, btrfs_leaf_data(leaf) + data_end + size_diff, old_data_start-data_end, old_data_start, data_end);
1296b18c6685SChris Mason 	btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1297b18c6685SChris Mason 		      data_end + size_diff, btrfs_leaf_data(leaf) +
1298b18c6685SChris Mason 		      data_end, old_data_start + new_size - data_end);
1299b18c6685SChris Mason 	btrfs_set_item_size(leaf->items + slot, new_size);
1300b18c6685SChris Mason 	btrfs_mark_buffer_dirty(leaf_buf);
1301b18c6685SChris Mason 
1302b18c6685SChris Mason 	ret = 0;
1303b18c6685SChris Mason 	if (btrfs_leaf_free_space(root, leaf) < 0)
1304b18c6685SChris Mason 		BUG();
1305b18c6685SChris Mason 	check_leaf(root, path, 0);
1306b18c6685SChris Mason 	return ret;
1307b18c6685SChris Mason }
1308b18c6685SChris Mason 
13096567e837SChris Mason int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
13106567e837SChris Mason 		      *root, struct btrfs_path *path, u32 data_size)
13116567e837SChris Mason {
13126567e837SChris Mason 	int ret = 0;
13136567e837SChris Mason 	int slot;
13146567e837SChris Mason 	int slot_orig;
13156567e837SChris Mason 	struct btrfs_leaf *leaf;
13166567e837SChris Mason 	struct buffer_head *leaf_buf;
13176567e837SChris Mason 	u32 nritems;
13186567e837SChris Mason 	unsigned int data_end;
13196567e837SChris Mason 	unsigned int old_data;
13206567e837SChris Mason 	unsigned int old_size;
13216567e837SChris Mason 	int i;
13226567e837SChris Mason 
13236567e837SChris Mason 	slot_orig = path->slots[0];
13246567e837SChris Mason 	leaf_buf = path->nodes[0];
13256567e837SChris Mason 	leaf = btrfs_buffer_leaf(leaf_buf);
13266567e837SChris Mason 
13276567e837SChris Mason 	nritems = btrfs_header_nritems(&leaf->header);
13286567e837SChris Mason 	data_end = leaf_data_end(root, leaf);
13296567e837SChris Mason 
13306567e837SChris Mason 	if (btrfs_leaf_free_space(root, leaf) < data_size)
13316567e837SChris Mason 		BUG();
13326567e837SChris Mason 	slot = path->slots[0];
13336567e837SChris Mason 	old_data = btrfs_item_end(leaf->items + slot);
13346567e837SChris Mason 
13356567e837SChris Mason 	BUG_ON(slot < 0);
13366567e837SChris Mason 	BUG_ON(slot >= nritems);
13376567e837SChris Mason 
13386567e837SChris Mason 	/*
13396567e837SChris Mason 	 * item0..itemN ... dataN.offset..dataN.size .. data0.size
13406567e837SChris Mason 	 */
13416567e837SChris Mason 	/* first correct the data pointers */
13426567e837SChris Mason 	for (i = slot; i < nritems; i++) {
13436567e837SChris Mason 		u32 ioff = btrfs_item_offset(leaf->items + i);
13446567e837SChris Mason 		btrfs_set_item_offset(leaf->items + i,
13456567e837SChris Mason 				      ioff - data_size);
13466567e837SChris Mason 	}
13476567e837SChris Mason 	/* shift the data */
13486567e837SChris Mason 	btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
13496567e837SChris Mason 		      data_end - data_size, btrfs_leaf_data(leaf) +
13506567e837SChris Mason 		      data_end, old_data - data_end);
13516567e837SChris Mason 	data_end = old_data;
13526567e837SChris Mason 	old_size = btrfs_item_size(leaf->items + slot);
13536567e837SChris Mason 	btrfs_set_item_size(leaf->items + slot, old_size + data_size);
13546567e837SChris Mason 	btrfs_mark_buffer_dirty(leaf_buf);
13556567e837SChris Mason 
13566567e837SChris Mason 	ret = 0;
13576567e837SChris Mason 	if (btrfs_leaf_free_space(root, leaf) < 0)
13586567e837SChris Mason 		BUG();
13596567e837SChris Mason 	check_leaf(root, path, 0);
13606567e837SChris Mason 	return ret;
13616567e837SChris Mason }
13626567e837SChris Mason 
136374123bd7SChris Mason /*
136474123bd7SChris Mason  * Given a key and some data, insert an item into the tree.
136574123bd7SChris Mason  * This does all the path init required, making room in the tree if needed.
136674123bd7SChris Mason  */
1367e089f05cSChris Mason int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
1368e089f05cSChris Mason 			    *root, struct btrfs_path *path, struct btrfs_key
1369e089f05cSChris Mason 			    *cpu_key, u32 data_size)
1370be0e5c09SChris Mason {
1371aa5d6bedSChris Mason 	int ret = 0;
1372be0e5c09SChris Mason 	int slot;
1373eb60ceacSChris Mason 	int slot_orig;
1374234b63a0SChris Mason 	struct btrfs_leaf *leaf;
1375e20d96d6SChris Mason 	struct buffer_head *leaf_buf;
13767518a238SChris Mason 	u32 nritems;
1377be0e5c09SChris Mason 	unsigned int data_end;
1378e2fa7227SChris Mason 	struct btrfs_disk_key disk_key;
1379e2fa7227SChris Mason 
1380e2fa7227SChris Mason 	btrfs_cpu_key_to_disk(&disk_key, cpu_key);
1381be0e5c09SChris Mason 
138274123bd7SChris Mason 	/* create a root if there isn't one */
13835c680ed6SChris Mason 	if (!root->node)
1384cfaa7295SChris Mason 		BUG();
1385e089f05cSChris Mason 	ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
1386eb60ceacSChris Mason 	if (ret == 0) {
1387f0930a37SChris Mason 		return -EEXIST;
1388aa5d6bedSChris Mason 	}
1389ed2ff2cbSChris Mason 	if (ret < 0)
1390ed2ff2cbSChris Mason 		goto out;
1391be0e5c09SChris Mason 
139262e2749eSChris Mason 	slot_orig = path->slots[0];
139362e2749eSChris Mason 	leaf_buf = path->nodes[0];
1394e20d96d6SChris Mason 	leaf = btrfs_buffer_leaf(leaf_buf);
139574123bd7SChris Mason 
13967518a238SChris Mason 	nritems = btrfs_header_nritems(&leaf->header);
1397123abc88SChris Mason 	data_end = leaf_data_end(root, leaf);
1398eb60ceacSChris Mason 
1399123abc88SChris Mason 	if (btrfs_leaf_free_space(root, leaf) <
1400d4dbff95SChris Mason 	    sizeof(struct btrfs_item) + data_size) {
1401be0e5c09SChris Mason 		BUG();
1402d4dbff95SChris Mason 	}
140362e2749eSChris Mason 	slot = path->slots[0];
1404eb60ceacSChris Mason 	BUG_ON(slot < 0);
1405be0e5c09SChris Mason 	if (slot != nritems) {
1406be0e5c09SChris Mason 		int i;
14070783fcfcSChris Mason 		unsigned int old_data = btrfs_item_end(leaf->items + slot);
1408be0e5c09SChris Mason 
1409be0e5c09SChris Mason 		/*
1410be0e5c09SChris Mason 		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1411be0e5c09SChris Mason 		 */
1412be0e5c09SChris Mason 		/* first correct the data pointers */
14130783fcfcSChris Mason 		for (i = slot; i < nritems; i++) {
1414123abc88SChris Mason 			u32 ioff = btrfs_item_offset(leaf->items + i);
14150783fcfcSChris Mason 			btrfs_set_item_offset(leaf->items + i,
14160783fcfcSChris Mason 					      ioff - data_size);
14170783fcfcSChris Mason 		}
1418be0e5c09SChris Mason 
1419be0e5c09SChris Mason 		/* shift the items */
1420d6025579SChris Mason 		btrfs_memmove(root, leaf, leaf->items + slot + 1,
1421d6025579SChris Mason 			      leaf->items + slot,
14220783fcfcSChris Mason 			      (nritems - slot) * sizeof(struct btrfs_item));
1423be0e5c09SChris Mason 
1424be0e5c09SChris Mason 		/* shift the data */
1425d6025579SChris Mason 		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1426d6025579SChris Mason 			      data_end - data_size, btrfs_leaf_data(leaf) +
1427be0e5c09SChris Mason 			      data_end, old_data - data_end);
1428be0e5c09SChris Mason 		data_end = old_data;
1429be0e5c09SChris Mason 	}
143062e2749eSChris Mason 	/* setup the item for the new data */
1431d6025579SChris Mason 	btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
1432e2fa7227SChris Mason 		     sizeof(struct btrfs_disk_key));
14330783fcfcSChris Mason 	btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
14340783fcfcSChris Mason 	btrfs_set_item_size(leaf->items + slot, data_size);
14357518a238SChris Mason 	btrfs_set_header_nritems(&leaf->header, nritems + 1);
1436d6025579SChris Mason 	btrfs_mark_buffer_dirty(leaf_buf);
1437aa5d6bedSChris Mason 
1438aa5d6bedSChris Mason 	ret = 0;
14398e19f2cdSChris Mason 	if (slot == 0)
1440e089f05cSChris Mason 		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
1441aa5d6bedSChris Mason 
1442123abc88SChris Mason 	if (btrfs_leaf_free_space(root, leaf) < 0)
1443be0e5c09SChris Mason 		BUG();
144462e2749eSChris Mason 	check_leaf(root, path, 0);
1445ed2ff2cbSChris Mason out:
144662e2749eSChris Mason 	return ret;
144762e2749eSChris Mason }
144862e2749eSChris Mason 
144962e2749eSChris Mason /*
145062e2749eSChris Mason  * Given a key and some data, insert an item into the tree.
145162e2749eSChris Mason  * This does all the path init required, making room in the tree if needed.
145262e2749eSChris Mason  */
1453e089f05cSChris Mason int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
1454e089f05cSChris Mason 		      *root, struct btrfs_key *cpu_key, void *data, u32
1455e089f05cSChris Mason 		      data_size)
145662e2749eSChris Mason {
145762e2749eSChris Mason 	int ret = 0;
14582c90e5d6SChris Mason 	struct btrfs_path *path;
145962e2749eSChris Mason 	u8 *ptr;
146062e2749eSChris Mason 
14612c90e5d6SChris Mason 	path = btrfs_alloc_path();
14622c90e5d6SChris Mason 	BUG_ON(!path);
14632c90e5d6SChris Mason 	btrfs_init_path(path);
14642c90e5d6SChris Mason 	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
146562e2749eSChris Mason 	if (!ret) {
14662c90e5d6SChris Mason 		ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
14672c90e5d6SChris Mason 				     path->slots[0], u8);
14682c90e5d6SChris Mason 		btrfs_memcpy(root, path->nodes[0]->b_data,
1469d6025579SChris Mason 			     ptr, data, data_size);
14702c90e5d6SChris Mason 		btrfs_mark_buffer_dirty(path->nodes[0]);
147162e2749eSChris Mason 	}
14722c90e5d6SChris Mason 	btrfs_release_path(root, path);
14732c90e5d6SChris Mason 	btrfs_free_path(path);
1474aa5d6bedSChris Mason 	return ret;
1475be0e5c09SChris Mason }
1476be0e5c09SChris Mason 
147774123bd7SChris Mason /*
14785de08d7dSChris Mason  * delete the pointer from a given node.
147974123bd7SChris Mason  *
148074123bd7SChris Mason  * If the delete empties a node, the node is removed from the tree,
148174123bd7SChris Mason  * continuing all the way the root if required.  The root is converted into
148274123bd7SChris Mason  * a leaf if all the nodes are emptied.
148374123bd7SChris Mason  */
1484e089f05cSChris Mason static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1485e089f05cSChris Mason 		   struct btrfs_path *path, int level, int slot)
1486be0e5c09SChris Mason {
1487234b63a0SChris Mason 	struct btrfs_node *node;
1488e20d96d6SChris Mason 	struct buffer_head *parent = path->nodes[level];
14897518a238SChris Mason 	u32 nritems;
1490aa5d6bedSChris Mason 	int ret = 0;
1491bb803951SChris Mason 	int wret;
1492be0e5c09SChris Mason 
1493e20d96d6SChris Mason 	node = btrfs_buffer_node(parent);
14947518a238SChris Mason 	nritems = btrfs_header_nritems(&node->header);
1495be0e5c09SChris Mason 	if (slot != nritems -1) {
1496d6025579SChris Mason 		btrfs_memmove(root, node, node->ptrs + slot,
1497d6025579SChris Mason 			      node->ptrs + slot + 1,
1498d6025579SChris Mason 			      sizeof(struct btrfs_key_ptr) *
1499d6025579SChris Mason 			      (nritems - slot - 1));
1500be0e5c09SChris Mason 	}
15017518a238SChris Mason 	nritems--;
15027518a238SChris Mason 	btrfs_set_header_nritems(&node->header, nritems);
15037518a238SChris Mason 	if (nritems == 0 && parent == root->node) {
1504e20d96d6SChris Mason 		struct btrfs_header *header = btrfs_buffer_header(root->node);
1505e20d96d6SChris Mason 		BUG_ON(btrfs_header_level(header) != 1);
1506eb60ceacSChris Mason 		/* just turn the root into a leaf and break */
1507e20d96d6SChris Mason 		btrfs_set_header_level(header, 0);
1508bb803951SChris Mason 	} else if (slot == 0) {
1509e089f05cSChris Mason 		wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
1510123abc88SChris Mason 				      level + 1);
15110f70abe2SChris Mason 		if (wret)
15120f70abe2SChris Mason 			ret = wret;
1513be0e5c09SChris Mason 	}
1514d6025579SChris Mason 	btrfs_mark_buffer_dirty(parent);
1515aa5d6bedSChris Mason 	return ret;
1516be0e5c09SChris Mason }
1517be0e5c09SChris Mason 
151874123bd7SChris Mason /*
151974123bd7SChris Mason  * delete the item at the leaf level in path.  If that empties
152074123bd7SChris Mason  * the leaf, remove it from the tree
152174123bd7SChris Mason  */
1522e089f05cSChris Mason int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1523e089f05cSChris Mason 		   struct btrfs_path *path)
1524be0e5c09SChris Mason {
1525be0e5c09SChris Mason 	int slot;
1526234b63a0SChris Mason 	struct btrfs_leaf *leaf;
1527e20d96d6SChris Mason 	struct buffer_head *leaf_buf;
1528be0e5c09SChris Mason 	int doff;
1529be0e5c09SChris Mason 	int dsize;
1530aa5d6bedSChris Mason 	int ret = 0;
1531aa5d6bedSChris Mason 	int wret;
15327518a238SChris Mason 	u32 nritems;
1533be0e5c09SChris Mason 
1534eb60ceacSChris Mason 	leaf_buf = path->nodes[0];
1535e20d96d6SChris Mason 	leaf = btrfs_buffer_leaf(leaf_buf);
15364920c9acSChris Mason 	slot = path->slots[0];
15370783fcfcSChris Mason 	doff = btrfs_item_offset(leaf->items + slot);
15380783fcfcSChris Mason 	dsize = btrfs_item_size(leaf->items + slot);
15397518a238SChris Mason 	nritems = btrfs_header_nritems(&leaf->header);
1540be0e5c09SChris Mason 
15417518a238SChris Mason 	if (slot != nritems - 1) {
1542be0e5c09SChris Mason 		int i;
1543123abc88SChris Mason 		int data_end = leaf_data_end(root, leaf);
1544d6025579SChris Mason 		btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1545d6025579SChris Mason 			      data_end + dsize,
1546123abc88SChris Mason 			      btrfs_leaf_data(leaf) + data_end,
1547be0e5c09SChris Mason 			      doff - data_end);
15480783fcfcSChris Mason 		for (i = slot + 1; i < nritems; i++) {
1549123abc88SChris Mason 			u32 ioff = btrfs_item_offset(leaf->items + i);
15500783fcfcSChris Mason 			btrfs_set_item_offset(leaf->items + i, ioff + dsize);
15510783fcfcSChris Mason 		}
1552d6025579SChris Mason 		btrfs_memmove(root, leaf, leaf->items + slot,
1553d6025579SChris Mason 			      leaf->items + slot + 1,
15540783fcfcSChris Mason 			      sizeof(struct btrfs_item) *
15557518a238SChris Mason 			      (nritems - slot - 1));
1556be0e5c09SChris Mason 	}
15577518a238SChris Mason 	btrfs_set_header_nritems(&leaf->header, nritems - 1);
15587518a238SChris Mason 	nritems--;
155974123bd7SChris Mason 	/* delete the leaf if we've emptied it */
15607518a238SChris Mason 	if (nritems == 0) {
1561eb60ceacSChris Mason 		if (leaf_buf == root->node) {
15627518a238SChris Mason 			btrfs_set_header_level(&leaf->header, 0);
15639a8dd150SChris Mason 		} else {
1564e089f05cSChris Mason 			clean_tree_block(trans, root, leaf_buf);
1565d6025579SChris Mason 			wait_on_buffer(leaf_buf);
1566e089f05cSChris Mason 			wret = del_ptr(trans, root, path, 1, path->slots[1]);
1567aa5d6bedSChris Mason 			if (wret)
1568aa5d6bedSChris Mason 				ret = wret;
1569e089f05cSChris Mason 			wret = btrfs_free_extent(trans, root,
15707eccb903SChris Mason 						 bh_blocknr(leaf_buf), 1, 1);
15710f70abe2SChris Mason 			if (wret)
15720f70abe2SChris Mason 				ret = wret;
15739a8dd150SChris Mason 		}
1574be0e5c09SChris Mason 	} else {
15757518a238SChris Mason 		int used = leaf_space_used(leaf, 0, nritems);
1576aa5d6bedSChris Mason 		if (slot == 0) {
1577e089f05cSChris Mason 			wret = fixup_low_keys(trans, root, path,
1578aa5d6bedSChris Mason 					      &leaf->items[0].key, 1);
1579aa5d6bedSChris Mason 			if (wret)
1580aa5d6bedSChris Mason 				ret = wret;
1581aa5d6bedSChris Mason 		}
1582aa5d6bedSChris Mason 
158374123bd7SChris Mason 		/* delete the leaf if it is mostly empty */
1584123abc88SChris Mason 		if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
1585be0e5c09SChris Mason 			/* push_leaf_left fixes the path.
1586be0e5c09SChris Mason 			 * make sure the path still points to our leaf
1587be0e5c09SChris Mason 			 * for possible call to del_ptr below
1588be0e5c09SChris Mason 			 */
15894920c9acSChris Mason 			slot = path->slots[1];
1590e20d96d6SChris Mason 			get_bh(leaf_buf);
1591e089f05cSChris Mason 			wret = push_leaf_left(trans, root, path, 1);
1592aa5d6bedSChris Mason 			if (wret < 0)
1593aa5d6bedSChris Mason 				ret = wret;
1594f0930a37SChris Mason 			if (path->nodes[0] == leaf_buf &&
15957518a238SChris Mason 			    btrfs_header_nritems(&leaf->header)) {
1596e089f05cSChris Mason 				wret = push_leaf_right(trans, root, path, 1);
1597aa5d6bedSChris Mason 				if (wret < 0)
1598aa5d6bedSChris Mason 					ret = wret;
1599aa5d6bedSChris Mason 			}
16007518a238SChris Mason 			if (btrfs_header_nritems(&leaf->header) == 0) {
16017eccb903SChris Mason 				u64 blocknr = bh_blocknr(leaf_buf);
1602e089f05cSChris Mason 				clean_tree_block(trans, root, leaf_buf);
1603d6025579SChris Mason 				wait_on_buffer(leaf_buf);
1604e089f05cSChris Mason 				wret = del_ptr(trans, root, path, 1, slot);
1605aa5d6bedSChris Mason 				if (wret)
1606aa5d6bedSChris Mason 					ret = wret;
1607234b63a0SChris Mason 				btrfs_block_release(root, leaf_buf);
1608e089f05cSChris Mason 				wret = btrfs_free_extent(trans, root, blocknr,
1609e089f05cSChris Mason 							 1, 1);
16100f70abe2SChris Mason 				if (wret)
16110f70abe2SChris Mason 					ret = wret;
16125de08d7dSChris Mason 			} else {
1613d6025579SChris Mason 				btrfs_mark_buffer_dirty(leaf_buf);
1614234b63a0SChris Mason 				btrfs_block_release(root, leaf_buf);
1615be0e5c09SChris Mason 			}
1616d5719762SChris Mason 		} else {
1617d6025579SChris Mason 			btrfs_mark_buffer_dirty(leaf_buf);
1618be0e5c09SChris Mason 		}
16199a8dd150SChris Mason 	}
1620aa5d6bedSChris Mason 	return ret;
16219a8dd150SChris Mason }
16229a8dd150SChris Mason 
162397571fd0SChris Mason /*
162497571fd0SChris Mason  * walk up the tree as far as required to find the next leaf.
16250f70abe2SChris Mason  * returns 0 if it found something or 1 if there are no greater leaves.
16260f70abe2SChris Mason  * returns < 0 on io errors.
162797571fd0SChris Mason  */
1628234b63a0SChris Mason int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
1629d97e63b6SChris Mason {
1630d97e63b6SChris Mason 	int slot;
1631d97e63b6SChris Mason 	int level = 1;
1632d97e63b6SChris Mason 	u64 blocknr;
1633e20d96d6SChris Mason 	struct buffer_head *c;
1634e20d96d6SChris Mason 	struct btrfs_node *c_node;
1635e20d96d6SChris Mason 	struct buffer_head *next = NULL;
1636d97e63b6SChris Mason 
1637234b63a0SChris Mason 	while(level < BTRFS_MAX_LEVEL) {
1638d97e63b6SChris Mason 		if (!path->nodes[level])
16390f70abe2SChris Mason 			return 1;
1640d97e63b6SChris Mason 		slot = path->slots[level] + 1;
1641d97e63b6SChris Mason 		c = path->nodes[level];
1642e20d96d6SChris Mason 		c_node = btrfs_buffer_node(c);
1643e20d96d6SChris Mason 		if (slot >= btrfs_header_nritems(&c_node->header)) {
1644d97e63b6SChris Mason 			level++;
1645d97e63b6SChris Mason 			continue;
1646d97e63b6SChris Mason 		}
1647e20d96d6SChris Mason 		blocknr = btrfs_node_blockptr(c_node, slot);
1648cfaa7295SChris Mason 		if (next)
1649234b63a0SChris Mason 			btrfs_block_release(root, next);
1650d97e63b6SChris Mason 		next = read_tree_block(root, blocknr);
1651d97e63b6SChris Mason 		break;
1652d97e63b6SChris Mason 	}
1653d97e63b6SChris Mason 	path->slots[level] = slot;
1654d97e63b6SChris Mason 	while(1) {
1655d97e63b6SChris Mason 		level--;
1656d97e63b6SChris Mason 		c = path->nodes[level];
1657234b63a0SChris Mason 		btrfs_block_release(root, c);
1658d97e63b6SChris Mason 		path->nodes[level] = next;
1659d97e63b6SChris Mason 		path->slots[level] = 0;
1660d97e63b6SChris Mason 		if (!level)
1661d97e63b6SChris Mason 			break;
16621d4f8a0cSChris Mason 		next = read_tree_block(root,
1663e20d96d6SChris Mason 		       btrfs_node_blockptr(btrfs_buffer_node(next), 0));
1664d97e63b6SChris Mason 	}
1665d97e63b6SChris Mason 	return 0;
1666d97e63b6SChris Mason }
1667