1*6cbd5570SChris Mason /* 2*6cbd5570SChris Mason * Copyright (C) 2007 Oracle. All rights reserved. 3*6cbd5570SChris Mason * 4*6cbd5570SChris Mason * This program is free software; you can redistribute it and/or 5*6cbd5570SChris Mason * modify it under the terms of the GNU General Public 6*6cbd5570SChris Mason * License v2 as published by the Free Software Foundation. 7*6cbd5570SChris Mason * 8*6cbd5570SChris Mason * This program is distributed in the hope that it will be useful, 9*6cbd5570SChris Mason * but WITHOUT ANY WARRANTY; without even the implied warranty of 10*6cbd5570SChris Mason * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11*6cbd5570SChris Mason * General Public License for more details. 12*6cbd5570SChris Mason * 13*6cbd5570SChris Mason * You should have received a copy of the GNU General Public 14*6cbd5570SChris Mason * License along with this program; if not, write to the 15*6cbd5570SChris Mason * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16*6cbd5570SChris Mason * Boston, MA 021110-1307, USA. 17*6cbd5570SChris Mason */ 18*6cbd5570SChris Mason 192e635a27SChris Mason #include <linux/module.h> 20eb60ceacSChris Mason #include "ctree.h" 21eb60ceacSChris Mason #include "disk-io.h" 227f5c1516SChris Mason #include "transaction.h" 239a8dd150SChris Mason 24e089f05cSChris Mason static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root 25e089f05cSChris Mason *root, struct btrfs_path *path, int level); 26e089f05cSChris Mason static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root 27d4dbff95SChris Mason *root, struct btrfs_key *ins_key, 28d4dbff95SChris Mason struct btrfs_path *path, int data_size); 29e089f05cSChris Mason static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root 30e20d96d6SChris Mason *root, struct buffer_head *dst, struct buffer_head 31e089f05cSChris Mason *src); 32e089f05cSChris Mason static int balance_node_right(struct btrfs_trans_handle *trans, struct 33e20d96d6SChris Mason btrfs_root *root, struct buffer_head *dst_buf, 34e20d96d6SChris Mason struct buffer_head *src_buf); 35e089f05cSChris Mason static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 36e089f05cSChris Mason struct btrfs_path *path, int level, int slot); 37d97e63b6SChris Mason 38df24a2b9SChris Mason inline void btrfs_init_path(struct btrfs_path *p) 39df24a2b9SChris Mason { 40df24a2b9SChris Mason memset(p, 0, sizeof(*p)); 41df24a2b9SChris Mason } 42df24a2b9SChris Mason 432c90e5d6SChris Mason struct btrfs_path *btrfs_alloc_path(void) 442c90e5d6SChris Mason { 45df24a2b9SChris Mason struct btrfs_path *path; 46df24a2b9SChris Mason path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS); 47df24a2b9SChris Mason if (path) 48df24a2b9SChris Mason btrfs_init_path(path); 49df24a2b9SChris Mason return path; 502c90e5d6SChris Mason } 512c90e5d6SChris Mason 522c90e5d6SChris Mason void btrfs_free_path(struct btrfs_path *p) 532c90e5d6SChris Mason { 54df24a2b9SChris Mason btrfs_release_path(NULL, p); 552c90e5d6SChris Mason kmem_cache_free(btrfs_path_cachep, p); 562c90e5d6SChris Mason } 572c90e5d6SChris Mason 58234b63a0SChris Mason void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) 59eb60ceacSChris Mason { 60eb60ceacSChris Mason int i; 61234b63a0SChris Mason for (i = 0; i < BTRFS_MAX_LEVEL; i++) { 62eb60ceacSChris Mason if (!p->nodes[i]) 63eb60ceacSChris Mason break; 64234b63a0SChris Mason btrfs_block_release(root, p->nodes[i]); 65eb60ceacSChris Mason } 66aa5d6bedSChris Mason memset(p, 0, sizeof(*p)); 67eb60ceacSChris Mason } 68eb60ceacSChris Mason 69e089f05cSChris Mason static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root 70e20d96d6SChris Mason *root, struct buffer_head *buf, struct buffer_head 71e20d96d6SChris Mason *parent, int parent_slot, struct buffer_head 72e089f05cSChris Mason **cow_ret) 7302217ed2SChris Mason { 74e20d96d6SChris Mason struct buffer_head *cow; 75e20d96d6SChris Mason struct btrfs_node *cow_node; 7602217ed2SChris Mason 777f5c1516SChris Mason if (btrfs_header_generation(btrfs_buffer_header(buf)) == 787f5c1516SChris Mason trans->transid) { 7902217ed2SChris Mason *cow_ret = buf; 8002217ed2SChris Mason return 0; 8102217ed2SChris Mason } 8231f3c99bSChris Mason cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr); 83e20d96d6SChris Mason cow_node = btrfs_buffer_node(cow); 842c90e5d6SChris Mason if (buf->b_size != root->blocksize || cow->b_size != root->blocksize) 852c90e5d6SChris Mason WARN_ON(1); 86e20d96d6SChris Mason memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); 877eccb903SChris Mason btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow)); 887f5c1516SChris Mason btrfs_set_header_generation(&cow_node->header, trans->transid); 894d775673SChris Mason btrfs_set_header_owner(&cow_node->header, root->root_key.objectid); 90e089f05cSChris Mason btrfs_inc_ref(trans, root, buf); 9102217ed2SChris Mason if (buf == root->node) { 9202217ed2SChris Mason root->node = cow; 93e20d96d6SChris Mason get_bh(cow); 942c90e5d6SChris Mason if (buf != root->commit_root) { 957eccb903SChris Mason btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1); 962c90e5d6SChris Mason } 97234b63a0SChris Mason btrfs_block_release(root, buf); 9802217ed2SChris Mason } else { 99e20d96d6SChris Mason btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, 1007eccb903SChris Mason bh_blocknr(cow)); 101d6025579SChris Mason btrfs_mark_buffer_dirty(parent); 1027eccb903SChris Mason btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1); 10302217ed2SChris Mason } 104234b63a0SChris Mason btrfs_block_release(root, buf); 105df24a2b9SChris Mason mark_buffer_dirty(cow); 1062c90e5d6SChris Mason *cow_ret = cow; 10702217ed2SChris Mason return 0; 10802217ed2SChris Mason } 10902217ed2SChris Mason 11074123bd7SChris Mason /* 11174123bd7SChris Mason * The leaf data grows from end-to-front in the node. 11274123bd7SChris Mason * this returns the address of the start of the last item, 11374123bd7SChris Mason * which is the stop of the leaf data stack 11474123bd7SChris Mason */ 115123abc88SChris Mason static inline unsigned int leaf_data_end(struct btrfs_root *root, 116123abc88SChris Mason struct btrfs_leaf *leaf) 117be0e5c09SChris Mason { 1187518a238SChris Mason u32 nr = btrfs_header_nritems(&leaf->header); 119be0e5c09SChris Mason if (nr == 0) 120123abc88SChris Mason return BTRFS_LEAF_DATA_SIZE(root); 1210783fcfcSChris Mason return btrfs_item_offset(leaf->items + nr - 1); 122be0e5c09SChris Mason } 123be0e5c09SChris Mason 12474123bd7SChris Mason /* 12574123bd7SChris Mason * compare two keys in a memcmp fashion 12674123bd7SChris Mason */ 1279aca1d51SChris Mason static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) 128be0e5c09SChris Mason { 129e2fa7227SChris Mason struct btrfs_key k1; 130e2fa7227SChris Mason 131e2fa7227SChris Mason btrfs_disk_key_to_cpu(&k1, disk); 132e2fa7227SChris Mason 133e2fa7227SChris Mason if (k1.objectid > k2->objectid) 134be0e5c09SChris Mason return 1; 135e2fa7227SChris Mason if (k1.objectid < k2->objectid) 136be0e5c09SChris Mason return -1; 137f254e52cSChris Mason if (k1.flags > k2->flags) 138f254e52cSChris Mason return 1; 139f254e52cSChris Mason if (k1.flags < k2->flags) 140f254e52cSChris Mason return -1; 14170b2befdSChris Mason if (k1.offset > k2->offset) 14270b2befdSChris Mason return 1; 14370b2befdSChris Mason if (k1.offset < k2->offset) 14470b2befdSChris Mason return -1; 145be0e5c09SChris Mason return 0; 146be0e5c09SChris Mason } 14774123bd7SChris Mason 148123abc88SChris Mason static int check_node(struct btrfs_root *root, struct btrfs_path *path, 149123abc88SChris Mason int level) 150aa5d6bedSChris Mason { 151234b63a0SChris Mason struct btrfs_node *parent = NULL; 152e20d96d6SChris Mason struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]); 153aa5d6bedSChris Mason int parent_slot; 1548d7be552SChris Mason int slot; 1558d7be552SChris Mason struct btrfs_key cpukey; 1567518a238SChris Mason u32 nritems = btrfs_header_nritems(&node->header); 157aa5d6bedSChris Mason 158aa5d6bedSChris Mason if (path->nodes[level + 1]) 159e20d96d6SChris Mason parent = btrfs_buffer_node(path->nodes[level + 1]); 160aa5d6bedSChris Mason parent_slot = path->slots[level + 1]; 1618d7be552SChris Mason slot = path->slots[level]; 1627518a238SChris Mason BUG_ON(nritems == 0); 1637518a238SChris Mason if (parent) { 164e2fa7227SChris Mason struct btrfs_disk_key *parent_key; 165123abc88SChris Mason parent_key = &parent->ptrs[parent_slot].key; 166123abc88SChris Mason BUG_ON(memcmp(parent_key, &node->ptrs[0].key, 167e2fa7227SChris Mason sizeof(struct btrfs_disk_key))); 1681d4f8a0cSChris Mason BUG_ON(btrfs_node_blockptr(parent, parent_slot) != 1697518a238SChris Mason btrfs_header_blocknr(&node->header)); 170aa5d6bedSChris Mason } 171123abc88SChris Mason BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root)); 1728d7be552SChris Mason if (slot != 0) { 1738d7be552SChris Mason btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot - 1].key); 1748d7be552SChris Mason BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) <= 0); 1758d7be552SChris Mason } 1768d7be552SChris Mason if (slot < nritems - 1) { 1778d7be552SChris Mason btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot + 1].key); 1788d7be552SChris Mason BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) >= 0); 179aa5d6bedSChris Mason } 180aa5d6bedSChris Mason return 0; 181aa5d6bedSChris Mason } 182aa5d6bedSChris Mason 183123abc88SChris Mason static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, 184123abc88SChris Mason int level) 185aa5d6bedSChris Mason { 186e20d96d6SChris Mason struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]); 187234b63a0SChris Mason struct btrfs_node *parent = NULL; 188aa5d6bedSChris Mason int parent_slot; 1898d7be552SChris Mason int slot = path->slots[0]; 1908d7be552SChris Mason struct btrfs_key cpukey; 1918d7be552SChris Mason 1927518a238SChris Mason u32 nritems = btrfs_header_nritems(&leaf->header); 193aa5d6bedSChris Mason 194aa5d6bedSChris Mason if (path->nodes[level + 1]) 195e20d96d6SChris Mason parent = btrfs_buffer_node(path->nodes[level + 1]); 196aa5d6bedSChris Mason parent_slot = path->slots[level + 1]; 197123abc88SChris Mason BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); 1987518a238SChris Mason 1997518a238SChris Mason if (nritems == 0) 2007518a238SChris Mason return 0; 2017518a238SChris Mason 2027518a238SChris Mason if (parent) { 203e2fa7227SChris Mason struct btrfs_disk_key *parent_key; 204123abc88SChris Mason parent_key = &parent->ptrs[parent_slot].key; 205aa5d6bedSChris Mason BUG_ON(memcmp(parent_key, &leaf->items[0].key, 206e2fa7227SChris Mason sizeof(struct btrfs_disk_key))); 2071d4f8a0cSChris Mason BUG_ON(btrfs_node_blockptr(parent, parent_slot) != 2087518a238SChris Mason btrfs_header_blocknr(&leaf->header)); 209aa5d6bedSChris Mason } 2108d7be552SChris Mason if (slot != 0) { 2118d7be552SChris Mason btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot - 1].key); 2128d7be552SChris Mason BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) <= 0); 2138d7be552SChris Mason BUG_ON(btrfs_item_offset(leaf->items + slot - 1) != 2148d7be552SChris Mason btrfs_item_end(leaf->items + slot)); 215aa5d6bedSChris Mason } 2168d7be552SChris Mason if (slot < nritems - 1) { 2178d7be552SChris Mason btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot + 1].key); 2188d7be552SChris Mason BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) >= 0); 2198d7be552SChris Mason BUG_ON(btrfs_item_offset(leaf->items + slot) != 2208d7be552SChris Mason btrfs_item_end(leaf->items + slot + 1)); 221aa5d6bedSChris Mason } 2228d7be552SChris Mason BUG_ON(btrfs_item_offset(leaf->items) + 2238d7be552SChris Mason btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root)); 224aa5d6bedSChris Mason return 0; 225aa5d6bedSChris Mason } 226aa5d6bedSChris Mason 227123abc88SChris Mason static int check_block(struct btrfs_root *root, struct btrfs_path *path, 228123abc88SChris Mason int level) 229aa5d6bedSChris Mason { 2303eb0314dSChris Mason struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]); 2313eb0314dSChris Mason if (memcmp(node->header.fsid, root->fs_info->disk_super->fsid, 2323eb0314dSChris Mason sizeof(node->header.fsid))) 2333eb0314dSChris Mason BUG(); 234aa5d6bedSChris Mason if (level == 0) 235123abc88SChris Mason return check_leaf(root, path, level); 236123abc88SChris Mason return check_node(root, path, level); 237aa5d6bedSChris Mason } 238aa5d6bedSChris Mason 23974123bd7SChris Mason /* 24074123bd7SChris Mason * search for key in the array p. items p are item_size apart 24174123bd7SChris Mason * and there are 'max' items in p 24274123bd7SChris Mason * the slot in the array is returned via slot, and it points to 24374123bd7SChris Mason * the place where you would insert key if it is not found in 24474123bd7SChris Mason * the array. 24574123bd7SChris Mason * 24674123bd7SChris Mason * slot may point to max if the key is bigger than all of the keys 24774123bd7SChris Mason */ 2489aca1d51SChris Mason static int generic_bin_search(char *p, int item_size, struct btrfs_key *key, 249be0e5c09SChris Mason int max, int *slot) 250be0e5c09SChris Mason { 251be0e5c09SChris Mason int low = 0; 252be0e5c09SChris Mason int high = max; 253be0e5c09SChris Mason int mid; 254be0e5c09SChris Mason int ret; 255e2fa7227SChris Mason struct btrfs_disk_key *tmp; 256be0e5c09SChris Mason 257be0e5c09SChris Mason while(low < high) { 258be0e5c09SChris Mason mid = (low + high) / 2; 259e2fa7227SChris Mason tmp = (struct btrfs_disk_key *)(p + mid * item_size); 260be0e5c09SChris Mason ret = comp_keys(tmp, key); 261be0e5c09SChris Mason 262be0e5c09SChris Mason if (ret < 0) 263be0e5c09SChris Mason low = mid + 1; 264be0e5c09SChris Mason else if (ret > 0) 265be0e5c09SChris Mason high = mid; 266be0e5c09SChris Mason else { 267be0e5c09SChris Mason *slot = mid; 268be0e5c09SChris Mason return 0; 269be0e5c09SChris Mason } 270be0e5c09SChris Mason } 271be0e5c09SChris Mason *slot = low; 272be0e5c09SChris Mason return 1; 273be0e5c09SChris Mason } 274be0e5c09SChris Mason 27597571fd0SChris Mason /* 27697571fd0SChris Mason * simple bin_search frontend that does the right thing for 27797571fd0SChris Mason * leaves vs nodes 27897571fd0SChris Mason */ 2799aca1d51SChris Mason static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot) 280be0e5c09SChris Mason { 2817518a238SChris Mason if (btrfs_is_leaf(c)) { 282234b63a0SChris Mason struct btrfs_leaf *l = (struct btrfs_leaf *)c; 2830783fcfcSChris Mason return generic_bin_search((void *)l->items, 2840783fcfcSChris Mason sizeof(struct btrfs_item), 2857518a238SChris Mason key, btrfs_header_nritems(&c->header), 2867518a238SChris Mason slot); 287be0e5c09SChris Mason } else { 288123abc88SChris Mason return generic_bin_search((void *)c->ptrs, 289123abc88SChris Mason sizeof(struct btrfs_key_ptr), 2907518a238SChris Mason key, btrfs_header_nritems(&c->header), 2917518a238SChris Mason slot); 292be0e5c09SChris Mason } 293be0e5c09SChris Mason return -1; 294be0e5c09SChris Mason } 295be0e5c09SChris Mason 296e20d96d6SChris Mason static struct buffer_head *read_node_slot(struct btrfs_root *root, 297e20d96d6SChris Mason struct buffer_head *parent_buf, 298bb803951SChris Mason int slot) 299bb803951SChris Mason { 300e20d96d6SChris Mason struct btrfs_node *node = btrfs_buffer_node(parent_buf); 301bb803951SChris Mason if (slot < 0) 302bb803951SChris Mason return NULL; 3037518a238SChris Mason if (slot >= btrfs_header_nritems(&node->header)) 304bb803951SChris Mason return NULL; 3051d4f8a0cSChris Mason return read_tree_block(root, btrfs_node_blockptr(node, slot)); 306bb803951SChris Mason } 307bb803951SChris Mason 308e089f05cSChris Mason static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root 309e089f05cSChris Mason *root, struct btrfs_path *path, int level) 310bb803951SChris Mason { 311e20d96d6SChris Mason struct buffer_head *right_buf; 312e20d96d6SChris Mason struct buffer_head *mid_buf; 313e20d96d6SChris Mason struct buffer_head *left_buf; 314e20d96d6SChris Mason struct buffer_head *parent_buf = NULL; 315234b63a0SChris Mason struct btrfs_node *right = NULL; 316234b63a0SChris Mason struct btrfs_node *mid; 317234b63a0SChris Mason struct btrfs_node *left = NULL; 318234b63a0SChris Mason struct btrfs_node *parent = NULL; 319bb803951SChris Mason int ret = 0; 320bb803951SChris Mason int wret; 321bb803951SChris Mason int pslot; 322bb803951SChris Mason int orig_slot = path->slots[level]; 32379f95c82SChris Mason u64 orig_ptr; 324bb803951SChris Mason 325bb803951SChris Mason if (level == 0) 326bb803951SChris Mason return 0; 327bb803951SChris Mason 328bb803951SChris Mason mid_buf = path->nodes[level]; 329e20d96d6SChris Mason mid = btrfs_buffer_node(mid_buf); 3301d4f8a0cSChris Mason orig_ptr = btrfs_node_blockptr(mid, orig_slot); 33179f95c82SChris Mason 332234b63a0SChris Mason if (level < BTRFS_MAX_LEVEL - 1) 333bb803951SChris Mason parent_buf = path->nodes[level + 1]; 334bb803951SChris Mason pslot = path->slots[level + 1]; 335bb803951SChris Mason 33640689478SChris Mason /* 33740689478SChris Mason * deal with the case where there is only one pointer in the root 33840689478SChris Mason * by promoting the node below to a root 33940689478SChris Mason */ 340bb803951SChris Mason if (!parent_buf) { 341e20d96d6SChris Mason struct buffer_head *child; 3427eccb903SChris Mason u64 blocknr = bh_blocknr(mid_buf); 343bb803951SChris Mason 3447518a238SChris Mason if (btrfs_header_nritems(&mid->header) != 1) 345bb803951SChris Mason return 0; 346bb803951SChris Mason 347bb803951SChris Mason /* promote the child to a root */ 348bb803951SChris Mason child = read_node_slot(root, mid_buf, 0); 349bb803951SChris Mason BUG_ON(!child); 350bb803951SChris Mason root->node = child; 351bb803951SChris Mason path->nodes[level] = NULL; 352d6025579SChris Mason clean_tree_block(trans, root, mid_buf); 353d6025579SChris Mason wait_on_buffer(mid_buf); 354bb803951SChris Mason /* once for the path */ 355234b63a0SChris Mason btrfs_block_release(root, mid_buf); 356bb803951SChris Mason /* once for the root ptr */ 357234b63a0SChris Mason btrfs_block_release(root, mid_buf); 358e089f05cSChris Mason return btrfs_free_extent(trans, root, blocknr, 1, 1); 359bb803951SChris Mason } 360e20d96d6SChris Mason parent = btrfs_buffer_node(parent_buf); 361bb803951SChris Mason 362123abc88SChris Mason if (btrfs_header_nritems(&mid->header) > 363123abc88SChris Mason BTRFS_NODEPTRS_PER_BLOCK(root) / 4) 364bb803951SChris Mason return 0; 365bb803951SChris Mason 366bb803951SChris Mason left_buf = read_node_slot(root, parent_buf, pslot - 1); 367bb803951SChris Mason right_buf = read_node_slot(root, parent_buf, pslot + 1); 36879f95c82SChris Mason 36979f95c82SChris Mason /* first, try to make some room in the middle buffer */ 370bb803951SChris Mason if (left_buf) { 371e089f05cSChris Mason btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1, 372e089f05cSChris Mason &left_buf); 373e20d96d6SChris Mason left = btrfs_buffer_node(left_buf); 3747518a238SChris Mason orig_slot += btrfs_header_nritems(&left->header); 375e089f05cSChris Mason wret = push_node_left(trans, root, left_buf, mid_buf); 37679f95c82SChris Mason if (wret < 0) 37779f95c82SChris Mason ret = wret; 378bb803951SChris Mason } 37979f95c82SChris Mason 38079f95c82SChris Mason /* 38179f95c82SChris Mason * then try to empty the right most buffer into the middle 38279f95c82SChris Mason */ 383bb803951SChris Mason if (right_buf) { 384e089f05cSChris Mason btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1, 385e089f05cSChris Mason &right_buf); 386e20d96d6SChris Mason right = btrfs_buffer_node(right_buf); 387e089f05cSChris Mason wret = push_node_left(trans, root, mid_buf, right_buf); 38879f95c82SChris Mason if (wret < 0) 38979f95c82SChris Mason ret = wret; 3907518a238SChris Mason if (btrfs_header_nritems(&right->header) == 0) { 3917eccb903SChris Mason u64 blocknr = bh_blocknr(right_buf); 392e089f05cSChris Mason clean_tree_block(trans, root, right_buf); 393d6025579SChris Mason wait_on_buffer(right_buf); 394d6025579SChris Mason btrfs_block_release(root, right_buf); 395bb803951SChris Mason right_buf = NULL; 396bb803951SChris Mason right = NULL; 397e089f05cSChris Mason wret = del_ptr(trans, root, path, level + 1, pslot + 398e089f05cSChris Mason 1); 399bb803951SChris Mason if (wret) 400bb803951SChris Mason ret = wret; 401e089f05cSChris Mason wret = btrfs_free_extent(trans, root, blocknr, 1, 1); 402bb803951SChris Mason if (wret) 403bb803951SChris Mason ret = wret; 404bb803951SChris Mason } else { 405d6025579SChris Mason btrfs_memcpy(root, parent, 406d6025579SChris Mason &parent->ptrs[pslot + 1].key, 407123abc88SChris Mason &right->ptrs[0].key, 408e2fa7227SChris Mason sizeof(struct btrfs_disk_key)); 409d6025579SChris Mason btrfs_mark_buffer_dirty(parent_buf); 410bb803951SChris Mason } 411bb803951SChris Mason } 4127518a238SChris Mason if (btrfs_header_nritems(&mid->header) == 1) { 41379f95c82SChris Mason /* 41479f95c82SChris Mason * we're not allowed to leave a node with one item in the 41579f95c82SChris Mason * tree during a delete. A deletion from lower in the tree 41679f95c82SChris Mason * could try to delete the only pointer in this node. 41779f95c82SChris Mason * So, pull some keys from the left. 41879f95c82SChris Mason * There has to be a left pointer at this point because 41979f95c82SChris Mason * otherwise we would have pulled some pointers from the 42079f95c82SChris Mason * right 42179f95c82SChris Mason */ 42279f95c82SChris Mason BUG_ON(!left_buf); 423e089f05cSChris Mason wret = balance_node_right(trans, root, mid_buf, left_buf); 42479f95c82SChris Mason if (wret < 0) 42579f95c82SChris Mason ret = wret; 42679f95c82SChris Mason BUG_ON(wret == 1); 42779f95c82SChris Mason } 4287518a238SChris Mason if (btrfs_header_nritems(&mid->header) == 0) { 42979f95c82SChris Mason /* we've managed to empty the middle node, drop it */ 4307eccb903SChris Mason u64 blocknr = bh_blocknr(mid_buf); 431e089f05cSChris Mason clean_tree_block(trans, root, mid_buf); 432d6025579SChris Mason wait_on_buffer(mid_buf); 433d6025579SChris Mason btrfs_block_release(root, mid_buf); 434bb803951SChris Mason mid_buf = NULL; 435bb803951SChris Mason mid = NULL; 436e089f05cSChris Mason wret = del_ptr(trans, root, path, level + 1, pslot); 437bb803951SChris Mason if (wret) 438bb803951SChris Mason ret = wret; 439e089f05cSChris Mason wret = btrfs_free_extent(trans, root, blocknr, 1, 1); 440bb803951SChris Mason if (wret) 441bb803951SChris Mason ret = wret; 44279f95c82SChris Mason } else { 44379f95c82SChris Mason /* update the parent key to reflect our changes */ 444d6025579SChris Mason btrfs_memcpy(root, parent, 445d6025579SChris Mason &parent->ptrs[pslot].key, &mid->ptrs[0].key, 446e2fa7227SChris Mason sizeof(struct btrfs_disk_key)); 447d6025579SChris Mason btrfs_mark_buffer_dirty(parent_buf); 44879f95c82SChris Mason } 449bb803951SChris Mason 45079f95c82SChris Mason /* update the path */ 451bb803951SChris Mason if (left_buf) { 4527518a238SChris Mason if (btrfs_header_nritems(&left->header) > orig_slot) { 453e20d96d6SChris Mason get_bh(left_buf); 454bb803951SChris Mason path->nodes[level] = left_buf; 455bb803951SChris Mason path->slots[level + 1] -= 1; 456bb803951SChris Mason path->slots[level] = orig_slot; 457bb803951SChris Mason if (mid_buf) 458234b63a0SChris Mason btrfs_block_release(root, mid_buf); 459bb803951SChris Mason } else { 4607518a238SChris Mason orig_slot -= btrfs_header_nritems(&left->header); 461bb803951SChris Mason path->slots[level] = orig_slot; 462bb803951SChris Mason } 463bb803951SChris Mason } 46479f95c82SChris Mason /* double check we haven't messed things up */ 465123abc88SChris Mason check_block(root, path, level); 466e20d96d6SChris Mason if (orig_ptr != 467e20d96d6SChris Mason btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]), 4681d4f8a0cSChris Mason path->slots[level])) 46979f95c82SChris Mason BUG(); 470bb803951SChris Mason 471bb803951SChris Mason if (right_buf) 472234b63a0SChris Mason btrfs_block_release(root, right_buf); 473bb803951SChris Mason if (left_buf) 474234b63a0SChris Mason btrfs_block_release(root, left_buf); 475bb803951SChris Mason return ret; 476bb803951SChris Mason } 477bb803951SChris Mason 478e66f709bSChris Mason /* returns zero if the push worked, non-zero otherwise */ 479e66f709bSChris Mason static int push_nodes_for_insert(struct btrfs_trans_handle *trans, 480e66f709bSChris Mason struct btrfs_root *root, 481e66f709bSChris Mason struct btrfs_path *path, int level) 482e66f709bSChris Mason { 483e66f709bSChris Mason struct buffer_head *right_buf; 484e66f709bSChris Mason struct buffer_head *mid_buf; 485e66f709bSChris Mason struct buffer_head *left_buf; 486e66f709bSChris Mason struct buffer_head *parent_buf = NULL; 487e66f709bSChris Mason struct btrfs_node *right = NULL; 488e66f709bSChris Mason struct btrfs_node *mid; 489e66f709bSChris Mason struct btrfs_node *left = NULL; 490e66f709bSChris Mason struct btrfs_node *parent = NULL; 491e66f709bSChris Mason int ret = 0; 492e66f709bSChris Mason int wret; 493e66f709bSChris Mason int pslot; 494e66f709bSChris Mason int orig_slot = path->slots[level]; 495e66f709bSChris Mason u64 orig_ptr; 496e66f709bSChris Mason 497e66f709bSChris Mason if (level == 0) 498e66f709bSChris Mason return 1; 499e66f709bSChris Mason 500e66f709bSChris Mason mid_buf = path->nodes[level]; 501e66f709bSChris Mason mid = btrfs_buffer_node(mid_buf); 502e66f709bSChris Mason orig_ptr = btrfs_node_blockptr(mid, orig_slot); 503e66f709bSChris Mason 504e66f709bSChris Mason if (level < BTRFS_MAX_LEVEL - 1) 505e66f709bSChris Mason parent_buf = path->nodes[level + 1]; 506e66f709bSChris Mason pslot = path->slots[level + 1]; 507e66f709bSChris Mason 508e66f709bSChris Mason if (!parent_buf) 509e66f709bSChris Mason return 1; 510e66f709bSChris Mason parent = btrfs_buffer_node(parent_buf); 511e66f709bSChris Mason 512e66f709bSChris Mason left_buf = read_node_slot(root, parent_buf, pslot - 1); 513e66f709bSChris Mason 514e66f709bSChris Mason /* first, try to make some room in the middle buffer */ 515e66f709bSChris Mason if (left_buf) { 516e66f709bSChris Mason u32 left_nr; 517e66f709bSChris Mason left = btrfs_buffer_node(left_buf); 518e66f709bSChris Mason left_nr = btrfs_header_nritems(&left->header); 51933ade1f8SChris Mason if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { 52033ade1f8SChris Mason wret = 1; 52133ade1f8SChris Mason } else { 52233ade1f8SChris Mason btrfs_cow_block(trans, root, left_buf, parent_buf, 52333ade1f8SChris Mason pslot - 1, &left_buf); 52433ade1f8SChris Mason left = btrfs_buffer_node(left_buf); 525e66f709bSChris Mason wret = push_node_left(trans, root, left_buf, mid_buf); 52633ade1f8SChris Mason } 527e66f709bSChris Mason if (wret < 0) 528e66f709bSChris Mason ret = wret; 529e66f709bSChris Mason if (wret == 0) { 530e66f709bSChris Mason orig_slot += left_nr; 531e66f709bSChris Mason btrfs_memcpy(root, parent, 532e66f709bSChris Mason &parent->ptrs[pslot].key, 533e66f709bSChris Mason &mid->ptrs[0].key, 534e66f709bSChris Mason sizeof(struct btrfs_disk_key)); 535e66f709bSChris Mason btrfs_mark_buffer_dirty(parent_buf); 536e66f709bSChris Mason if (btrfs_header_nritems(&left->header) > orig_slot) { 537e66f709bSChris Mason path->nodes[level] = left_buf; 538e66f709bSChris Mason path->slots[level + 1] -= 1; 539e66f709bSChris Mason path->slots[level] = orig_slot; 540e66f709bSChris Mason btrfs_block_release(root, mid_buf); 541e66f709bSChris Mason } else { 542e66f709bSChris Mason orig_slot -= 543e66f709bSChris Mason btrfs_header_nritems(&left->header); 544e66f709bSChris Mason path->slots[level] = orig_slot; 545e66f709bSChris Mason btrfs_block_release(root, left_buf); 546e66f709bSChris Mason } 547e66f709bSChris Mason check_node(root, path, level); 548e66f709bSChris Mason return 0; 549e66f709bSChris Mason } 550e66f709bSChris Mason btrfs_block_release(root, left_buf); 551e66f709bSChris Mason } 552e66f709bSChris Mason right_buf = read_node_slot(root, parent_buf, pslot + 1); 553e66f709bSChris Mason 554e66f709bSChris Mason /* 555e66f709bSChris Mason * then try to empty the right most buffer into the middle 556e66f709bSChris Mason */ 557e66f709bSChris Mason if (right_buf) { 55833ade1f8SChris Mason u32 right_nr; 559e66f709bSChris Mason right = btrfs_buffer_node(right_buf); 56033ade1f8SChris Mason right_nr = btrfs_header_nritems(&right->header); 56133ade1f8SChris Mason if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { 56233ade1f8SChris Mason wret = 1; 56333ade1f8SChris Mason } else { 56433ade1f8SChris Mason btrfs_cow_block(trans, root, right_buf, 56533ade1f8SChris Mason parent_buf, pslot + 1, &right_buf); 56633ade1f8SChris Mason right = btrfs_buffer_node(right_buf); 56733ade1f8SChris Mason wret = balance_node_right(trans, root, 56833ade1f8SChris Mason right_buf, mid_buf); 56933ade1f8SChris Mason } 570e66f709bSChris Mason if (wret < 0) 571e66f709bSChris Mason ret = wret; 572e66f709bSChris Mason if (wret == 0) { 573e66f709bSChris Mason btrfs_memcpy(root, parent, 574e66f709bSChris Mason &parent->ptrs[pslot + 1].key, 575e66f709bSChris Mason &right->ptrs[0].key, 576e66f709bSChris Mason sizeof(struct btrfs_disk_key)); 577e66f709bSChris Mason btrfs_mark_buffer_dirty(parent_buf); 578e66f709bSChris Mason if (btrfs_header_nritems(&mid->header) <= orig_slot) { 579e66f709bSChris Mason path->nodes[level] = right_buf; 580e66f709bSChris Mason path->slots[level + 1] += 1; 581e66f709bSChris Mason path->slots[level] = orig_slot - 582e66f709bSChris Mason btrfs_header_nritems(&mid->header); 583e66f709bSChris Mason btrfs_block_release(root, mid_buf); 584e66f709bSChris Mason } else { 585e66f709bSChris Mason btrfs_block_release(root, right_buf); 586e66f709bSChris Mason } 587e66f709bSChris Mason check_node(root, path, level); 588e66f709bSChris Mason return 0; 589e66f709bSChris Mason } 590e66f709bSChris Mason btrfs_block_release(root, right_buf); 591e66f709bSChris Mason } 592e66f709bSChris Mason check_node(root, path, level); 593e66f709bSChris Mason return 1; 594e66f709bSChris Mason } 595e66f709bSChris Mason 59674123bd7SChris Mason /* 59774123bd7SChris Mason * look for key in the tree. path is filled in with nodes along the way 59874123bd7SChris Mason * if key is found, we return zero and you can find the item in the leaf 59974123bd7SChris Mason * level of the path (level 0) 60074123bd7SChris Mason * 60174123bd7SChris Mason * If the key isn't found, the path points to the slot where it should 602aa5d6bedSChris Mason * be inserted, and 1 is returned. If there are other errors during the 603aa5d6bedSChris Mason * search a negative error number is returned. 60497571fd0SChris Mason * 60597571fd0SChris Mason * if ins_len > 0, nodes and leaves will be split as we walk down the 60697571fd0SChris Mason * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if 60797571fd0SChris Mason * possible) 60874123bd7SChris Mason */ 609e089f05cSChris Mason int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root 610e089f05cSChris Mason *root, struct btrfs_key *key, struct btrfs_path *p, int 611e089f05cSChris Mason ins_len, int cow) 612be0e5c09SChris Mason { 613e20d96d6SChris Mason struct buffer_head *b; 614e20d96d6SChris Mason struct buffer_head *cow_buf; 615234b63a0SChris Mason struct btrfs_node *c; 616be0e5c09SChris Mason int slot; 617be0e5c09SChris Mason int ret; 618be0e5c09SChris Mason int level; 6195c680ed6SChris Mason 62022b0ebdaSChris Mason WARN_ON(p->nodes[0] != NULL); 62122b0ebdaSChris Mason WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex)); 622bb803951SChris Mason again: 623bb803951SChris Mason b = root->node; 624e20d96d6SChris Mason get_bh(b); 625eb60ceacSChris Mason while (b) { 626e20d96d6SChris Mason c = btrfs_buffer_node(b); 627e20d96d6SChris Mason level = btrfs_header_level(&c->header); 62802217ed2SChris Mason if (cow) { 62902217ed2SChris Mason int wret; 630e20d96d6SChris Mason wret = btrfs_cow_block(trans, root, b, 631e20d96d6SChris Mason p->nodes[level + 1], 632e20d96d6SChris Mason p->slots[level + 1], 633e089f05cSChris Mason &cow_buf); 63402217ed2SChris Mason b = cow_buf; 6352c90e5d6SChris Mason c = btrfs_buffer_node(b); 63602217ed2SChris Mason } 63702217ed2SChris Mason BUG_ON(!cow && ins_len); 6382c90e5d6SChris Mason if (level != btrfs_header_level(&c->header)) 6392c90e5d6SChris Mason WARN_ON(1); 6402c90e5d6SChris Mason level = btrfs_header_level(&c->header); 641eb60ceacSChris Mason p->nodes[level] = b; 642123abc88SChris Mason ret = check_block(root, p, level); 643aa5d6bedSChris Mason if (ret) 644aa5d6bedSChris Mason return -1; 645be0e5c09SChris Mason ret = bin_search(c, key, &slot); 6467518a238SChris Mason if (!btrfs_is_leaf(c)) { 647be0e5c09SChris Mason if (ret && slot > 0) 648be0e5c09SChris Mason slot -= 1; 649be0e5c09SChris Mason p->slots[level] = slot; 650d4dbff95SChris Mason if (ins_len > 0 && btrfs_header_nritems(&c->header) >= 651d4dbff95SChris Mason BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { 652e089f05cSChris Mason int sret = split_node(trans, root, p, level); 6535c680ed6SChris Mason BUG_ON(sret > 0); 6545c680ed6SChris Mason if (sret) 6555c680ed6SChris Mason return sret; 6565c680ed6SChris Mason b = p->nodes[level]; 657e20d96d6SChris Mason c = btrfs_buffer_node(b); 6585c680ed6SChris Mason slot = p->slots[level]; 659bb803951SChris Mason } else if (ins_len < 0) { 660e089f05cSChris Mason int sret = balance_level(trans, root, p, 661e089f05cSChris Mason level); 662bb803951SChris Mason if (sret) 663bb803951SChris Mason return sret; 664bb803951SChris Mason b = p->nodes[level]; 665bb803951SChris Mason if (!b) 666bb803951SChris Mason goto again; 667e20d96d6SChris Mason c = btrfs_buffer_node(b); 668bb803951SChris Mason slot = p->slots[level]; 6697518a238SChris Mason BUG_ON(btrfs_header_nritems(&c->header) == 1); 6705c680ed6SChris Mason } 6711d4f8a0cSChris Mason b = read_tree_block(root, btrfs_node_blockptr(c, slot)); 672be0e5c09SChris Mason } else { 673234b63a0SChris Mason struct btrfs_leaf *l = (struct btrfs_leaf *)c; 674be0e5c09SChris Mason p->slots[level] = slot; 675123abc88SChris Mason if (ins_len > 0 && btrfs_leaf_free_space(root, l) < 6760783fcfcSChris Mason sizeof(struct btrfs_item) + ins_len) { 677d4dbff95SChris Mason int sret = split_leaf(trans, root, key, 678d4dbff95SChris Mason p, ins_len); 6795c680ed6SChris Mason BUG_ON(sret > 0); 6805c680ed6SChris Mason if (sret) 6815c680ed6SChris Mason return sret; 6825c680ed6SChris Mason } 683be0e5c09SChris Mason return ret; 684be0e5c09SChris Mason } 685be0e5c09SChris Mason } 686aa5d6bedSChris Mason return 1; 687be0e5c09SChris Mason } 688be0e5c09SChris Mason 68974123bd7SChris Mason /* 69074123bd7SChris Mason * adjust the pointers going up the tree, starting at level 69174123bd7SChris Mason * making sure the right key of each node is points to 'key'. 69274123bd7SChris Mason * This is used after shifting pointers to the left, so it stops 69374123bd7SChris Mason * fixing up pointers when a given leaf/node is not in slot 0 of the 69474123bd7SChris Mason * higher levels 695aa5d6bedSChris Mason * 696aa5d6bedSChris Mason * If this fails to write a tree block, it returns -1, but continues 697aa5d6bedSChris Mason * fixing up the blocks in ram so the tree is consistent. 69874123bd7SChris Mason */ 699e089f05cSChris Mason static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root 700e089f05cSChris Mason *root, struct btrfs_path *path, struct btrfs_disk_key 701e089f05cSChris Mason *key, int level) 702be0e5c09SChris Mason { 703be0e5c09SChris Mason int i; 704aa5d6bedSChris Mason int ret = 0; 705234b63a0SChris Mason for (i = level; i < BTRFS_MAX_LEVEL; i++) { 706234b63a0SChris Mason struct btrfs_node *t; 707be0e5c09SChris Mason int tslot = path->slots[i]; 708eb60ceacSChris Mason if (!path->nodes[i]) 709be0e5c09SChris Mason break; 710e20d96d6SChris Mason t = btrfs_buffer_node(path->nodes[i]); 711d6025579SChris Mason btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key)); 712d6025579SChris Mason btrfs_mark_buffer_dirty(path->nodes[i]); 713be0e5c09SChris Mason if (tslot != 0) 714be0e5c09SChris Mason break; 715be0e5c09SChris Mason } 716aa5d6bedSChris Mason return ret; 717be0e5c09SChris Mason } 718be0e5c09SChris Mason 71974123bd7SChris Mason /* 72074123bd7SChris Mason * try to push data from one node into the next node left in the 72179f95c82SChris Mason * tree. 722aa5d6bedSChris Mason * 723aa5d6bedSChris Mason * returns 0 if some ptrs were pushed left, < 0 if there was some horrible 724aa5d6bedSChris Mason * error, and > 0 if there was no room in the left hand block. 72574123bd7SChris Mason */ 726e089f05cSChris Mason static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root 727e20d96d6SChris Mason *root, struct buffer_head *dst_buf, struct 728e20d96d6SChris Mason buffer_head *src_buf) 729be0e5c09SChris Mason { 730e20d96d6SChris Mason struct btrfs_node *src = btrfs_buffer_node(src_buf); 731e20d96d6SChris Mason struct btrfs_node *dst = btrfs_buffer_node(dst_buf); 732be0e5c09SChris Mason int push_items = 0; 733bb803951SChris Mason int src_nritems; 734bb803951SChris Mason int dst_nritems; 735aa5d6bedSChris Mason int ret = 0; 736be0e5c09SChris Mason 7377518a238SChris Mason src_nritems = btrfs_header_nritems(&src->header); 7387518a238SChris Mason dst_nritems = btrfs_header_nritems(&dst->header); 739123abc88SChris Mason push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; 740eb60ceacSChris Mason if (push_items <= 0) { 741be0e5c09SChris Mason return 1; 742eb60ceacSChris Mason } 743be0e5c09SChris Mason 744be0e5c09SChris Mason if (src_nritems < push_items) 745be0e5c09SChris Mason push_items = src_nritems; 74679f95c82SChris Mason 747d6025579SChris Mason btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs, 748123abc88SChris Mason push_items * sizeof(struct btrfs_key_ptr)); 749bb803951SChris Mason if (push_items < src_nritems) { 750d6025579SChris Mason btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items, 751e2fa7227SChris Mason (src_nritems - push_items) * 752123abc88SChris Mason sizeof(struct btrfs_key_ptr)); 753bb803951SChris Mason } 7547518a238SChris Mason btrfs_set_header_nritems(&src->header, src_nritems - push_items); 7557518a238SChris Mason btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); 756d6025579SChris Mason btrfs_mark_buffer_dirty(src_buf); 757d6025579SChris Mason btrfs_mark_buffer_dirty(dst_buf); 758bb803951SChris Mason return ret; 759be0e5c09SChris Mason } 760be0e5c09SChris Mason 76197571fd0SChris Mason /* 76279f95c82SChris Mason * try to push data from one node into the next node right in the 76379f95c82SChris Mason * tree. 76479f95c82SChris Mason * 76579f95c82SChris Mason * returns 0 if some ptrs were pushed, < 0 if there was some horrible 76679f95c82SChris Mason * error, and > 0 if there was no room in the right hand block. 76779f95c82SChris Mason * 76879f95c82SChris Mason * this will only push up to 1/2 the contents of the left node over 76979f95c82SChris Mason */ 770e089f05cSChris Mason static int balance_node_right(struct btrfs_trans_handle *trans, struct 771e20d96d6SChris Mason btrfs_root *root, struct buffer_head *dst_buf, 772e20d96d6SChris Mason struct buffer_head *src_buf) 77379f95c82SChris Mason { 774e20d96d6SChris Mason struct btrfs_node *src = btrfs_buffer_node(src_buf); 775e20d96d6SChris Mason struct btrfs_node *dst = btrfs_buffer_node(dst_buf); 77679f95c82SChris Mason int push_items = 0; 77779f95c82SChris Mason int max_push; 77879f95c82SChris Mason int src_nritems; 77979f95c82SChris Mason int dst_nritems; 78079f95c82SChris Mason int ret = 0; 78179f95c82SChris Mason 7827518a238SChris Mason src_nritems = btrfs_header_nritems(&src->header); 7837518a238SChris Mason dst_nritems = btrfs_header_nritems(&dst->header); 784123abc88SChris Mason push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; 78579f95c82SChris Mason if (push_items <= 0) { 78679f95c82SChris Mason return 1; 78779f95c82SChris Mason } 78879f95c82SChris Mason 78979f95c82SChris Mason max_push = src_nritems / 2 + 1; 79079f95c82SChris Mason /* don't try to empty the node */ 79179f95c82SChris Mason if (max_push > src_nritems) 79279f95c82SChris Mason return 1; 79379f95c82SChris Mason if (max_push < push_items) 79479f95c82SChris Mason push_items = max_push; 79579f95c82SChris Mason 796d6025579SChris Mason btrfs_memmove(root, dst, dst->ptrs + push_items, dst->ptrs, 797123abc88SChris Mason dst_nritems * sizeof(struct btrfs_key_ptr)); 798d6025579SChris Mason 799d6025579SChris Mason btrfs_memcpy(root, dst, dst->ptrs, 800d6025579SChris Mason src->ptrs + src_nritems - push_items, 801123abc88SChris Mason push_items * sizeof(struct btrfs_key_ptr)); 80279f95c82SChris Mason 8037518a238SChris Mason btrfs_set_header_nritems(&src->header, src_nritems - push_items); 8047518a238SChris Mason btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); 80579f95c82SChris Mason 806d6025579SChris Mason btrfs_mark_buffer_dirty(src_buf); 807d6025579SChris Mason btrfs_mark_buffer_dirty(dst_buf); 80879f95c82SChris Mason return ret; 80979f95c82SChris Mason } 81079f95c82SChris Mason 81179f95c82SChris Mason /* 81297571fd0SChris Mason * helper function to insert a new root level in the tree. 81397571fd0SChris Mason * A new node is allocated, and a single item is inserted to 81497571fd0SChris Mason * point to the existing root 815aa5d6bedSChris Mason * 816aa5d6bedSChris Mason * returns zero on success or < 0 on failure. 81797571fd0SChris Mason */ 818e089f05cSChris Mason static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root 819e089f05cSChris Mason *root, struct btrfs_path *path, int level) 82074123bd7SChris Mason { 821e20d96d6SChris Mason struct buffer_head *t; 822234b63a0SChris Mason struct btrfs_node *lower; 823234b63a0SChris Mason struct btrfs_node *c; 824e2fa7227SChris Mason struct btrfs_disk_key *lower_key; 8255c680ed6SChris Mason 8265c680ed6SChris Mason BUG_ON(path->nodes[level]); 8275c680ed6SChris Mason BUG_ON(path->nodes[level-1] != root->node); 8285c680ed6SChris Mason 82931f3c99bSChris Mason t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr); 830e20d96d6SChris Mason c = btrfs_buffer_node(t); 831123abc88SChris Mason memset(c, 0, root->blocksize); 8327518a238SChris Mason btrfs_set_header_nritems(&c->header, 1); 8337518a238SChris Mason btrfs_set_header_level(&c->header, level); 8347eccb903SChris Mason btrfs_set_header_blocknr(&c->header, bh_blocknr(t)); 8357f5c1516SChris Mason btrfs_set_header_generation(&c->header, trans->transid); 8364d775673SChris Mason btrfs_set_header_owner(&c->header, root->root_key.objectid); 837e20d96d6SChris Mason lower = btrfs_buffer_node(path->nodes[level-1]); 8383eb0314dSChris Mason memcpy(c->header.fsid, root->fs_info->disk_super->fsid, 8393eb0314dSChris Mason sizeof(c->header.fsid)); 8407518a238SChris Mason if (btrfs_is_leaf(lower)) 841234b63a0SChris Mason lower_key = &((struct btrfs_leaf *)lower)->items[0].key; 84274123bd7SChris Mason else 843123abc88SChris Mason lower_key = &lower->ptrs[0].key; 844d6025579SChris Mason btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key, 845d6025579SChris Mason sizeof(struct btrfs_disk_key)); 8467eccb903SChris Mason btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1])); 847d5719762SChris Mason 848d6025579SChris Mason btrfs_mark_buffer_dirty(t); 849d5719762SChris Mason 850cfaa7295SChris Mason /* the super has an extra ref to root->node */ 851234b63a0SChris Mason btrfs_block_release(root, root->node); 85274123bd7SChris Mason root->node = t; 853e20d96d6SChris Mason get_bh(t); 85474123bd7SChris Mason path->nodes[level] = t; 85574123bd7SChris Mason path->slots[level] = 0; 85674123bd7SChris Mason return 0; 85774123bd7SChris Mason } 8585c680ed6SChris Mason 8595c680ed6SChris Mason /* 8605c680ed6SChris Mason * worker function to insert a single pointer in a node. 8615c680ed6SChris Mason * the node should have enough room for the pointer already 86297571fd0SChris Mason * 8635c680ed6SChris Mason * slot and level indicate where you want the key to go, and 8645c680ed6SChris Mason * blocknr is the block the key points to. 865aa5d6bedSChris Mason * 866aa5d6bedSChris Mason * returns zero on success and < 0 on any error 8675c680ed6SChris Mason */ 868e089f05cSChris Mason static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root 869e089f05cSChris Mason *root, struct btrfs_path *path, struct btrfs_disk_key 870e089f05cSChris Mason *key, u64 blocknr, int slot, int level) 8715c680ed6SChris Mason { 872234b63a0SChris Mason struct btrfs_node *lower; 8735c680ed6SChris Mason int nritems; 8745c680ed6SChris Mason 8755c680ed6SChris Mason BUG_ON(!path->nodes[level]); 876e20d96d6SChris Mason lower = btrfs_buffer_node(path->nodes[level]); 8777518a238SChris Mason nritems = btrfs_header_nritems(&lower->header); 87874123bd7SChris Mason if (slot > nritems) 87974123bd7SChris Mason BUG(); 880123abc88SChris Mason if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root)) 88174123bd7SChris Mason BUG(); 88274123bd7SChris Mason if (slot != nritems) { 883d6025579SChris Mason btrfs_memmove(root, lower, lower->ptrs + slot + 1, 884d6025579SChris Mason lower->ptrs + slot, 885123abc88SChris Mason (nritems - slot) * sizeof(struct btrfs_key_ptr)); 88674123bd7SChris Mason } 887d6025579SChris Mason btrfs_memcpy(root, lower, &lower->ptrs[slot].key, 888d6025579SChris Mason key, sizeof(struct btrfs_disk_key)); 8891d4f8a0cSChris Mason btrfs_set_node_blockptr(lower, slot, blocknr); 8907518a238SChris Mason btrfs_set_header_nritems(&lower->header, nritems + 1); 891d6025579SChris Mason btrfs_mark_buffer_dirty(path->nodes[level]); 892098f59c2SChris Mason check_node(root, path, level); 89374123bd7SChris Mason return 0; 89474123bd7SChris Mason } 89574123bd7SChris Mason 89697571fd0SChris Mason /* 89797571fd0SChris Mason * split the node at the specified level in path in two. 89897571fd0SChris Mason * The path is corrected to point to the appropriate node after the split 89997571fd0SChris Mason * 90097571fd0SChris Mason * Before splitting this tries to make some room in the node by pushing 90197571fd0SChris Mason * left and right, if either one works, it returns right away. 902aa5d6bedSChris Mason * 903aa5d6bedSChris Mason * returns 0 on success and < 0 on failure 90497571fd0SChris Mason */ 905e089f05cSChris Mason static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root 906e089f05cSChris Mason *root, struct btrfs_path *path, int level) 907be0e5c09SChris Mason { 908e20d96d6SChris Mason struct buffer_head *t; 909234b63a0SChris Mason struct btrfs_node *c; 910e20d96d6SChris Mason struct buffer_head *split_buffer; 911234b63a0SChris Mason struct btrfs_node *split; 912be0e5c09SChris Mason int mid; 9135c680ed6SChris Mason int ret; 914aa5d6bedSChris Mason int wret; 9157518a238SChris Mason u32 c_nritems; 916be0e5c09SChris Mason 9175c680ed6SChris Mason t = path->nodes[level]; 918e20d96d6SChris Mason c = btrfs_buffer_node(t); 9195c680ed6SChris Mason if (t == root->node) { 9205c680ed6SChris Mason /* trying to split the root, lets make a new one */ 921e089f05cSChris Mason ret = insert_new_root(trans, root, path, level + 1); 9225c680ed6SChris Mason if (ret) 9235c680ed6SChris Mason return ret; 924e66f709bSChris Mason } else { 925e66f709bSChris Mason ret = push_nodes_for_insert(trans, root, path, level); 926e66f709bSChris Mason t = path->nodes[level]; 927e66f709bSChris Mason c = btrfs_buffer_node(t); 928e66f709bSChris Mason if (!ret && 929e66f709bSChris Mason btrfs_header_nritems(&c->header) < 930e66f709bSChris Mason BTRFS_NODEPTRS_PER_BLOCK(root) - 1) 931e66f709bSChris Mason return 0; 9325c680ed6SChris Mason } 933e66f709bSChris Mason 9347518a238SChris Mason c_nritems = btrfs_header_nritems(&c->header); 93531f3c99bSChris Mason split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr); 936e20d96d6SChris Mason split = btrfs_buffer_node(split_buffer); 9377518a238SChris Mason btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); 9389a6f11edSChris Mason btrfs_set_header_level(&split->header, btrfs_header_level(&c->header)); 9397eccb903SChris Mason btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer)); 9407f5c1516SChris Mason btrfs_set_header_generation(&split->header, trans->transid); 9414d775673SChris Mason btrfs_set_header_owner(&split->header, root->root_key.objectid); 9423eb0314dSChris Mason memcpy(split->header.fsid, root->fs_info->disk_super->fsid, 9433eb0314dSChris Mason sizeof(split->header.fsid)); 9447518a238SChris Mason mid = (c_nritems + 1) / 2; 945d6025579SChris Mason btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid, 946123abc88SChris Mason (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); 9477518a238SChris Mason btrfs_set_header_nritems(&split->header, c_nritems - mid); 9487518a238SChris Mason btrfs_set_header_nritems(&c->header, mid); 949aa5d6bedSChris Mason ret = 0; 950aa5d6bedSChris Mason 951d6025579SChris Mason btrfs_mark_buffer_dirty(t); 952d6025579SChris Mason btrfs_mark_buffer_dirty(split_buffer); 953e089f05cSChris Mason wret = insert_ptr(trans, root, path, &split->ptrs[0].key, 9547eccb903SChris Mason bh_blocknr(split_buffer), path->slots[level + 1] + 1, 955123abc88SChris Mason level + 1); 956aa5d6bedSChris Mason if (wret) 957aa5d6bedSChris Mason ret = wret; 958aa5d6bedSChris Mason 9595de08d7dSChris Mason if (path->slots[level] >= mid) { 9605c680ed6SChris Mason path->slots[level] -= mid; 961234b63a0SChris Mason btrfs_block_release(root, t); 9625c680ed6SChris Mason path->nodes[level] = split_buffer; 9635c680ed6SChris Mason path->slots[level + 1] += 1; 964eb60ceacSChris Mason } else { 965234b63a0SChris Mason btrfs_block_release(root, split_buffer); 966be0e5c09SChris Mason } 967aa5d6bedSChris Mason return ret; 968be0e5c09SChris Mason } 969be0e5c09SChris Mason 97074123bd7SChris Mason /* 97174123bd7SChris Mason * how many bytes are required to store the items in a leaf. start 97274123bd7SChris Mason * and nr indicate which items in the leaf to check. This totals up the 97374123bd7SChris Mason * space used both by the item structs and the item data 97474123bd7SChris Mason */ 975234b63a0SChris Mason static int leaf_space_used(struct btrfs_leaf *l, int start, int nr) 976be0e5c09SChris Mason { 977be0e5c09SChris Mason int data_len; 978d4dbff95SChris Mason int nritems = btrfs_header_nritems(&l->header); 979d4dbff95SChris Mason int end = min(nritems, start + nr) - 1; 980be0e5c09SChris Mason 981be0e5c09SChris Mason if (!nr) 982be0e5c09SChris Mason return 0; 9830783fcfcSChris Mason data_len = btrfs_item_end(l->items + start); 9840783fcfcSChris Mason data_len = data_len - btrfs_item_offset(l->items + end); 9850783fcfcSChris Mason data_len += sizeof(struct btrfs_item) * nr; 986d4dbff95SChris Mason WARN_ON(data_len < 0); 987be0e5c09SChris Mason return data_len; 988be0e5c09SChris Mason } 989be0e5c09SChris Mason 99074123bd7SChris Mason /* 991d4dbff95SChris Mason * The space between the end of the leaf items and 992d4dbff95SChris Mason * the start of the leaf data. IOW, how much room 993d4dbff95SChris Mason * the leaf has left for both items and data 994d4dbff95SChris Mason */ 995d4dbff95SChris Mason int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf) 996d4dbff95SChris Mason { 997d4dbff95SChris Mason int nritems = btrfs_header_nritems(&leaf->header); 998d4dbff95SChris Mason return BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems); 999d4dbff95SChris Mason } 1000d4dbff95SChris Mason 1001d4dbff95SChris Mason /* 100200ec4c51SChris Mason * push some data in the path leaf to the right, trying to free up at 100300ec4c51SChris Mason * least data_size bytes. returns zero if the push worked, nonzero otherwise 1004aa5d6bedSChris Mason * 1005aa5d6bedSChris Mason * returns 1 if the push failed because the other node didn't have enough 1006aa5d6bedSChris Mason * room, 0 if everything worked out and < 0 if there were major errors. 100700ec4c51SChris Mason */ 1008e089f05cSChris Mason static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root 1009e089f05cSChris Mason *root, struct btrfs_path *path, int data_size) 101000ec4c51SChris Mason { 1011e20d96d6SChris Mason struct buffer_head *left_buf = path->nodes[0]; 1012e20d96d6SChris Mason struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf); 1013234b63a0SChris Mason struct btrfs_leaf *right; 1014e20d96d6SChris Mason struct buffer_head *right_buf; 1015e20d96d6SChris Mason struct buffer_head *upper; 1016e20d96d6SChris Mason struct btrfs_node *upper_node; 101700ec4c51SChris Mason int slot; 101800ec4c51SChris Mason int i; 101900ec4c51SChris Mason int free_space; 102000ec4c51SChris Mason int push_space = 0; 102100ec4c51SChris Mason int push_items = 0; 10220783fcfcSChris Mason struct btrfs_item *item; 10237518a238SChris Mason u32 left_nritems; 10247518a238SChris Mason u32 right_nritems; 102500ec4c51SChris Mason 102600ec4c51SChris Mason slot = path->slots[1]; 102700ec4c51SChris Mason if (!path->nodes[1]) { 102800ec4c51SChris Mason return 1; 102900ec4c51SChris Mason } 103000ec4c51SChris Mason upper = path->nodes[1]; 1031e20d96d6SChris Mason upper_node = btrfs_buffer_node(upper); 1032e20d96d6SChris Mason if (slot >= btrfs_header_nritems(&upper_node->header) - 1) { 103300ec4c51SChris Mason return 1; 103400ec4c51SChris Mason } 1035e20d96d6SChris Mason right_buf = read_tree_block(root, 1036e20d96d6SChris Mason btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1)); 1037e20d96d6SChris Mason right = btrfs_buffer_leaf(right_buf); 1038123abc88SChris Mason free_space = btrfs_leaf_free_space(root, right); 10390783fcfcSChris Mason if (free_space < data_size + sizeof(struct btrfs_item)) { 1040234b63a0SChris Mason btrfs_block_release(root, right_buf); 104100ec4c51SChris Mason return 1; 104200ec4c51SChris Mason } 104302217ed2SChris Mason /* cow and double check */ 1044e089f05cSChris Mason btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf); 1045e20d96d6SChris Mason right = btrfs_buffer_leaf(right_buf); 1046123abc88SChris Mason free_space = btrfs_leaf_free_space(root, right); 10470783fcfcSChris Mason if (free_space < data_size + sizeof(struct btrfs_item)) { 1048234b63a0SChris Mason btrfs_block_release(root, right_buf); 104902217ed2SChris Mason return 1; 105002217ed2SChris Mason } 105102217ed2SChris Mason 10527518a238SChris Mason left_nritems = btrfs_header_nritems(&left->header); 1053a429e513SChris Mason if (left_nritems == 0) { 1054a429e513SChris Mason btrfs_block_release(root, right_buf); 1055a429e513SChris Mason return 1; 1056a429e513SChris Mason } 1057a429e513SChris Mason for (i = left_nritems - 1; i >= 1; i--) { 105800ec4c51SChris Mason item = left->items + i; 105900ec4c51SChris Mason if (path->slots[0] == i) 106000ec4c51SChris Mason push_space += data_size + sizeof(*item); 10610783fcfcSChris Mason if (btrfs_item_size(item) + sizeof(*item) + push_space > 10620783fcfcSChris Mason free_space) 106300ec4c51SChris Mason break; 106400ec4c51SChris Mason push_items++; 10650783fcfcSChris Mason push_space += btrfs_item_size(item) + sizeof(*item); 106600ec4c51SChris Mason } 106700ec4c51SChris Mason if (push_items == 0) { 1068234b63a0SChris Mason btrfs_block_release(root, right_buf); 106900ec4c51SChris Mason return 1; 107000ec4c51SChris Mason } 1071a429e513SChris Mason if (push_items == left_nritems) 1072a429e513SChris Mason WARN_ON(1); 10737518a238SChris Mason right_nritems = btrfs_header_nritems(&right->header); 107400ec4c51SChris Mason /* push left to right */ 10750783fcfcSChris Mason push_space = btrfs_item_end(left->items + left_nritems - push_items); 1076123abc88SChris Mason push_space -= leaf_data_end(root, left); 107700ec4c51SChris Mason /* make room in the right data area */ 1078d6025579SChris Mason btrfs_memmove(root, right, btrfs_leaf_data(right) + 1079d6025579SChris Mason leaf_data_end(root, right) - push_space, 1080d6025579SChris Mason btrfs_leaf_data(right) + 1081d6025579SChris Mason leaf_data_end(root, right), BTRFS_LEAF_DATA_SIZE(root) - 1082d6025579SChris Mason leaf_data_end(root, right)); 108300ec4c51SChris Mason /* copy from the left data area */ 1084d6025579SChris Mason btrfs_memcpy(root, right, btrfs_leaf_data(right) + 1085d6025579SChris Mason BTRFS_LEAF_DATA_SIZE(root) - push_space, 1086d6025579SChris Mason btrfs_leaf_data(left) + leaf_data_end(root, left), 1087d6025579SChris Mason push_space); 1088d6025579SChris Mason btrfs_memmove(root, right, right->items + push_items, right->items, 10890783fcfcSChris Mason right_nritems * sizeof(struct btrfs_item)); 109000ec4c51SChris Mason /* copy the items from left to right */ 1091d6025579SChris Mason btrfs_memcpy(root, right, right->items, left->items + 1092d6025579SChris Mason left_nritems - push_items, 10930783fcfcSChris Mason push_items * sizeof(struct btrfs_item)); 109400ec4c51SChris Mason 109500ec4c51SChris Mason /* update the item pointers */ 10967518a238SChris Mason right_nritems += push_items; 10977518a238SChris Mason btrfs_set_header_nritems(&right->header, right_nritems); 1098123abc88SChris Mason push_space = BTRFS_LEAF_DATA_SIZE(root); 10997518a238SChris Mason for (i = 0; i < right_nritems; i++) { 11000783fcfcSChris Mason btrfs_set_item_offset(right->items + i, push_space - 11010783fcfcSChris Mason btrfs_item_size(right->items + i)); 11020783fcfcSChris Mason push_space = btrfs_item_offset(right->items + i); 110300ec4c51SChris Mason } 11047518a238SChris Mason left_nritems -= push_items; 11057518a238SChris Mason btrfs_set_header_nritems(&left->header, left_nritems); 110600ec4c51SChris Mason 1107d6025579SChris Mason btrfs_mark_buffer_dirty(left_buf); 1108d6025579SChris Mason btrfs_mark_buffer_dirty(right_buf); 1109a429e513SChris Mason 1110d6025579SChris Mason btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key, 1111e2fa7227SChris Mason &right->items[0].key, sizeof(struct btrfs_disk_key)); 1112d6025579SChris Mason btrfs_mark_buffer_dirty(upper); 111302217ed2SChris Mason 111400ec4c51SChris Mason /* then fixup the leaf pointer in the path */ 11157518a238SChris Mason if (path->slots[0] >= left_nritems) { 11167518a238SChris Mason path->slots[0] -= left_nritems; 1117234b63a0SChris Mason btrfs_block_release(root, path->nodes[0]); 111800ec4c51SChris Mason path->nodes[0] = right_buf; 111900ec4c51SChris Mason path->slots[1] += 1; 112000ec4c51SChris Mason } else { 1121234b63a0SChris Mason btrfs_block_release(root, right_buf); 112200ec4c51SChris Mason } 1123098f59c2SChris Mason if (path->nodes[1]) 1124098f59c2SChris Mason check_node(root, path, 1); 112500ec4c51SChris Mason return 0; 112600ec4c51SChris Mason } 112700ec4c51SChris Mason /* 112874123bd7SChris Mason * push some data in the path leaf to the left, trying to free up at 112974123bd7SChris Mason * least data_size bytes. returns zero if the push worked, nonzero otherwise 113074123bd7SChris Mason */ 1131e089f05cSChris Mason static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root 1132e089f05cSChris Mason *root, struct btrfs_path *path, int data_size) 1133be0e5c09SChris Mason { 1134e20d96d6SChris Mason struct buffer_head *right_buf = path->nodes[0]; 1135e20d96d6SChris Mason struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf); 1136e20d96d6SChris Mason struct buffer_head *t; 1137234b63a0SChris Mason struct btrfs_leaf *left; 1138be0e5c09SChris Mason int slot; 1139be0e5c09SChris Mason int i; 1140be0e5c09SChris Mason int free_space; 1141be0e5c09SChris Mason int push_space = 0; 1142be0e5c09SChris Mason int push_items = 0; 11430783fcfcSChris Mason struct btrfs_item *item; 11447518a238SChris Mason u32 old_left_nritems; 1145aa5d6bedSChris Mason int ret = 0; 1146aa5d6bedSChris Mason int wret; 1147be0e5c09SChris Mason 1148be0e5c09SChris Mason slot = path->slots[1]; 1149be0e5c09SChris Mason if (slot == 0) { 1150be0e5c09SChris Mason return 1; 1151be0e5c09SChris Mason } 1152be0e5c09SChris Mason if (!path->nodes[1]) { 1153be0e5c09SChris Mason return 1; 1154be0e5c09SChris Mason } 1155e20d96d6SChris Mason t = read_tree_block(root, 1156e20d96d6SChris Mason btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1)); 1157e20d96d6SChris Mason left = btrfs_buffer_leaf(t); 1158123abc88SChris Mason free_space = btrfs_leaf_free_space(root, left); 11590783fcfcSChris Mason if (free_space < data_size + sizeof(struct btrfs_item)) { 1160234b63a0SChris Mason btrfs_block_release(root, t); 1161be0e5c09SChris Mason return 1; 1162be0e5c09SChris Mason } 116302217ed2SChris Mason 116402217ed2SChris Mason /* cow and double check */ 1165e089f05cSChris Mason btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); 1166e20d96d6SChris Mason left = btrfs_buffer_leaf(t); 1167123abc88SChris Mason free_space = btrfs_leaf_free_space(root, left); 11680783fcfcSChris Mason if (free_space < data_size + sizeof(struct btrfs_item)) { 1169234b63a0SChris Mason btrfs_block_release(root, t); 117002217ed2SChris Mason return 1; 117102217ed2SChris Mason } 117202217ed2SChris Mason 1173a429e513SChris Mason if (btrfs_header_nritems(&right->header) == 0) { 1174a429e513SChris Mason btrfs_block_release(root, t); 1175a429e513SChris Mason return 1; 1176a429e513SChris Mason } 1177a429e513SChris Mason 1178a429e513SChris Mason for (i = 0; i < btrfs_header_nritems(&right->header) - 1; i++) { 1179be0e5c09SChris Mason item = right->items + i; 1180be0e5c09SChris Mason if (path->slots[0] == i) 1181be0e5c09SChris Mason push_space += data_size + sizeof(*item); 11820783fcfcSChris Mason if (btrfs_item_size(item) + sizeof(*item) + push_space > 11830783fcfcSChris Mason free_space) 1184be0e5c09SChris Mason break; 1185be0e5c09SChris Mason push_items++; 11860783fcfcSChris Mason push_space += btrfs_item_size(item) + sizeof(*item); 1187be0e5c09SChris Mason } 1188be0e5c09SChris Mason if (push_items == 0) { 1189234b63a0SChris Mason btrfs_block_release(root, t); 1190be0e5c09SChris Mason return 1; 1191be0e5c09SChris Mason } 1192a429e513SChris Mason if (push_items == btrfs_header_nritems(&right->header)) 1193a429e513SChris Mason WARN_ON(1); 1194be0e5c09SChris Mason /* push data from right to left */ 1195d6025579SChris Mason btrfs_memcpy(root, left, left->items + 1196d6025579SChris Mason btrfs_header_nritems(&left->header), 11970783fcfcSChris Mason right->items, push_items * sizeof(struct btrfs_item)); 1198123abc88SChris Mason push_space = BTRFS_LEAF_DATA_SIZE(root) - 11990783fcfcSChris Mason btrfs_item_offset(right->items + push_items -1); 1200d6025579SChris Mason btrfs_memcpy(root, left, btrfs_leaf_data(left) + 1201d6025579SChris Mason leaf_data_end(root, left) - push_space, 1202123abc88SChris Mason btrfs_leaf_data(right) + 1203123abc88SChris Mason btrfs_item_offset(right->items + push_items - 1), 1204be0e5c09SChris Mason push_space); 12057518a238SChris Mason old_left_nritems = btrfs_header_nritems(&left->header); 1206eb60ceacSChris Mason BUG_ON(old_left_nritems < 0); 1207eb60ceacSChris Mason 1208be0e5c09SChris Mason for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { 1209123abc88SChris Mason u32 ioff = btrfs_item_offset(left->items + i); 1210123abc88SChris Mason btrfs_set_item_offset(left->items + i, ioff - 1211123abc88SChris Mason (BTRFS_LEAF_DATA_SIZE(root) - 12120783fcfcSChris Mason btrfs_item_offset(left->items + 12130783fcfcSChris Mason old_left_nritems - 1))); 1214be0e5c09SChris Mason } 12157518a238SChris Mason btrfs_set_header_nritems(&left->header, old_left_nritems + push_items); 1216be0e5c09SChris Mason 1217be0e5c09SChris Mason /* fixup right node */ 12180783fcfcSChris Mason push_space = btrfs_item_offset(right->items + push_items - 1) - 1219123abc88SChris Mason leaf_data_end(root, right); 1220d6025579SChris Mason btrfs_memmove(root, right, btrfs_leaf_data(right) + 1221d6025579SChris Mason BTRFS_LEAF_DATA_SIZE(root) - push_space, 1222d6025579SChris Mason btrfs_leaf_data(right) + 1223123abc88SChris Mason leaf_data_end(root, right), push_space); 1224d6025579SChris Mason btrfs_memmove(root, right, right->items, right->items + push_items, 12257518a238SChris Mason (btrfs_header_nritems(&right->header) - push_items) * 12260783fcfcSChris Mason sizeof(struct btrfs_item)); 12277518a238SChris Mason btrfs_set_header_nritems(&right->header, 12287518a238SChris Mason btrfs_header_nritems(&right->header) - 12297518a238SChris Mason push_items); 1230123abc88SChris Mason push_space = BTRFS_LEAF_DATA_SIZE(root); 1231eb60ceacSChris Mason 12327518a238SChris Mason for (i = 0; i < btrfs_header_nritems(&right->header); i++) { 12330783fcfcSChris Mason btrfs_set_item_offset(right->items + i, push_space - 12340783fcfcSChris Mason btrfs_item_size(right->items + i)); 12350783fcfcSChris Mason push_space = btrfs_item_offset(right->items + i); 1236be0e5c09SChris Mason } 1237eb60ceacSChris Mason 1238d6025579SChris Mason btrfs_mark_buffer_dirty(t); 1239d6025579SChris Mason btrfs_mark_buffer_dirty(right_buf); 1240098f59c2SChris Mason 1241e089f05cSChris Mason wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); 1242aa5d6bedSChris Mason if (wret) 1243aa5d6bedSChris Mason ret = wret; 1244be0e5c09SChris Mason 1245be0e5c09SChris Mason /* then fixup the leaf pointer in the path */ 1246be0e5c09SChris Mason if (path->slots[0] < push_items) { 1247be0e5c09SChris Mason path->slots[0] += old_left_nritems; 1248234b63a0SChris Mason btrfs_block_release(root, path->nodes[0]); 1249eb60ceacSChris Mason path->nodes[0] = t; 1250be0e5c09SChris Mason path->slots[1] -= 1; 1251be0e5c09SChris Mason } else { 1252234b63a0SChris Mason btrfs_block_release(root, t); 1253be0e5c09SChris Mason path->slots[0] -= push_items; 1254be0e5c09SChris Mason } 1255eb60ceacSChris Mason BUG_ON(path->slots[0] < 0); 1256098f59c2SChris Mason if (path->nodes[1]) 1257098f59c2SChris Mason check_node(root, path, 1); 1258aa5d6bedSChris Mason return ret; 1259be0e5c09SChris Mason } 1260be0e5c09SChris Mason 126174123bd7SChris Mason /* 126274123bd7SChris Mason * split the path's leaf in two, making sure there is at least data_size 126374123bd7SChris Mason * available for the resulting leaf level of the path. 1264aa5d6bedSChris Mason * 1265aa5d6bedSChris Mason * returns 0 if all went well and < 0 on failure. 126674123bd7SChris Mason */ 1267e089f05cSChris Mason static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root 1268d4dbff95SChris Mason *root, struct btrfs_key *ins_key, 1269d4dbff95SChris Mason struct btrfs_path *path, int data_size) 1270be0e5c09SChris Mason { 1271e20d96d6SChris Mason struct buffer_head *l_buf; 1272234b63a0SChris Mason struct btrfs_leaf *l; 12737518a238SChris Mason u32 nritems; 1274eb60ceacSChris Mason int mid; 1275eb60ceacSChris Mason int slot; 1276234b63a0SChris Mason struct btrfs_leaf *right; 1277e20d96d6SChris Mason struct buffer_head *right_buffer; 12780783fcfcSChris Mason int space_needed = data_size + sizeof(struct btrfs_item); 1279be0e5c09SChris Mason int data_copy_size; 1280be0e5c09SChris Mason int rt_data_off; 1281be0e5c09SChris Mason int i; 1282d4dbff95SChris Mason int ret = 0; 1283aa5d6bedSChris Mason int wret; 1284d4dbff95SChris Mason int double_split = 0; 1285d4dbff95SChris Mason struct btrfs_disk_key disk_key; 1286be0e5c09SChris Mason 128740689478SChris Mason /* first try to make some room by pushing left and right */ 1288e089f05cSChris Mason wret = push_leaf_left(trans, root, path, data_size); 1289eaee50e8SChris Mason if (wret < 0) 1290eaee50e8SChris Mason return wret; 1291eaee50e8SChris Mason if (wret) { 1292e089f05cSChris Mason wret = push_leaf_right(trans, root, path, data_size); 1293eaee50e8SChris Mason if (wret < 0) 1294eaee50e8SChris Mason return wret; 1295eaee50e8SChris Mason } 1296eb60ceacSChris Mason l_buf = path->nodes[0]; 1297e20d96d6SChris Mason l = btrfs_buffer_leaf(l_buf); 1298aa5d6bedSChris Mason 1299aa5d6bedSChris Mason /* did the pushes work? */ 1300123abc88SChris Mason if (btrfs_leaf_free_space(root, l) >= 1301123abc88SChris Mason sizeof(struct btrfs_item) + data_size) 1302be0e5c09SChris Mason return 0; 1303aa5d6bedSChris Mason 13045c680ed6SChris Mason if (!path->nodes[1]) { 1305e089f05cSChris Mason ret = insert_new_root(trans, root, path, 1); 13065c680ed6SChris Mason if (ret) 13075c680ed6SChris Mason return ret; 13085c680ed6SChris Mason } 1309eb60ceacSChris Mason slot = path->slots[0]; 13107518a238SChris Mason nritems = btrfs_header_nritems(&l->header); 1311eb60ceacSChris Mason mid = (nritems + 1)/ 2; 131231f3c99bSChris Mason right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr); 1313eb60ceacSChris Mason BUG_ON(!right_buffer); 1314e20d96d6SChris Mason right = btrfs_buffer_leaf(right_buffer); 1315123abc88SChris Mason memset(&right->header, 0, sizeof(right->header)); 13167eccb903SChris Mason btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); 13177f5c1516SChris Mason btrfs_set_header_generation(&right->header, trans->transid); 13184d775673SChris Mason btrfs_set_header_owner(&right->header, root->root_key.objectid); 13197518a238SChris Mason btrfs_set_header_level(&right->header, 0); 13203eb0314dSChris Mason memcpy(right->header.fsid, root->fs_info->disk_super->fsid, 13213eb0314dSChris Mason sizeof(right->header.fsid)); 1322d4dbff95SChris Mason if (mid <= slot) { 1323d4dbff95SChris Mason if (nritems == 1 || 1324d4dbff95SChris Mason leaf_space_used(l, mid, nritems - mid) + space_needed > 1325d4dbff95SChris Mason BTRFS_LEAF_DATA_SIZE(root)) { 1326d4dbff95SChris Mason if (slot >= nritems) { 1327d4dbff95SChris Mason btrfs_cpu_key_to_disk(&disk_key, ins_key); 1328d4dbff95SChris Mason btrfs_set_header_nritems(&right->header, 0); 1329d4dbff95SChris Mason wret = insert_ptr(trans, root, path, 1330d4dbff95SChris Mason &disk_key, 13317eccb903SChris Mason bh_blocknr(right_buffer), 1332d4dbff95SChris Mason path->slots[1] + 1, 1); 1333d4dbff95SChris Mason if (wret) 1334d4dbff95SChris Mason ret = wret; 1335d4dbff95SChris Mason btrfs_block_release(root, path->nodes[0]); 1336d4dbff95SChris Mason path->nodes[0] = right_buffer; 1337d4dbff95SChris Mason path->slots[0] = 0; 1338d4dbff95SChris Mason path->slots[1] += 1; 1339d4dbff95SChris Mason return ret; 1340d4dbff95SChris Mason } 1341d4dbff95SChris Mason mid = slot; 1342d4dbff95SChris Mason double_split = 1; 1343d4dbff95SChris Mason } 1344d4dbff95SChris Mason } else { 1345d4dbff95SChris Mason if (leaf_space_used(l, 0, mid + 1) + space_needed > 1346d4dbff95SChris Mason BTRFS_LEAF_DATA_SIZE(root)) { 1347d4dbff95SChris Mason if (slot == 0) { 1348d4dbff95SChris Mason btrfs_cpu_key_to_disk(&disk_key, ins_key); 1349d4dbff95SChris Mason btrfs_set_header_nritems(&right->header, 0); 1350d4dbff95SChris Mason wret = insert_ptr(trans, root, path, 1351d4dbff95SChris Mason &disk_key, 13527eccb903SChris Mason bh_blocknr(right_buffer), 1353098f59c2SChris Mason path->slots[1], 1); 1354d4dbff95SChris Mason if (wret) 1355d4dbff95SChris Mason ret = wret; 1356d4dbff95SChris Mason btrfs_block_release(root, path->nodes[0]); 1357d4dbff95SChris Mason path->nodes[0] = right_buffer; 1358d4dbff95SChris Mason path->slots[0] = 0; 1359a429e513SChris Mason if (path->slots[1] == 0) { 1360a429e513SChris Mason wret = fixup_low_keys(trans, root, 1361a429e513SChris Mason path, &disk_key, 1); 1362a429e513SChris Mason if (wret) 1363a429e513SChris Mason ret = wret; 1364a429e513SChris Mason } 1365d4dbff95SChris Mason return ret; 1366d4dbff95SChris Mason } 1367d4dbff95SChris Mason mid = slot; 1368d4dbff95SChris Mason double_split = 1; 1369d4dbff95SChris Mason } 1370d4dbff95SChris Mason } 1371d4dbff95SChris Mason btrfs_set_header_nritems(&right->header, nritems - mid); 1372123abc88SChris Mason data_copy_size = btrfs_item_end(l->items + mid) - 1373123abc88SChris Mason leaf_data_end(root, l); 1374d6025579SChris Mason btrfs_memcpy(root, right, right->items, l->items + mid, 13750783fcfcSChris Mason (nritems - mid) * sizeof(struct btrfs_item)); 1376d6025579SChris Mason btrfs_memcpy(root, right, 1377d6025579SChris Mason btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - 1378123abc88SChris Mason data_copy_size, btrfs_leaf_data(l) + 1379123abc88SChris Mason leaf_data_end(root, l), data_copy_size); 1380123abc88SChris Mason rt_data_off = BTRFS_LEAF_DATA_SIZE(root) - 1381123abc88SChris Mason btrfs_item_end(l->items + mid); 138274123bd7SChris Mason 13830783fcfcSChris Mason for (i = 0; i < btrfs_header_nritems(&right->header); i++) { 1384123abc88SChris Mason u32 ioff = btrfs_item_offset(right->items + i); 13850783fcfcSChris Mason btrfs_set_item_offset(right->items + i, ioff + rt_data_off); 13860783fcfcSChris Mason } 138774123bd7SChris Mason 13887518a238SChris Mason btrfs_set_header_nritems(&l->header, mid); 1389aa5d6bedSChris Mason ret = 0; 1390e089f05cSChris Mason wret = insert_ptr(trans, root, path, &right->items[0].key, 13917eccb903SChris Mason bh_blocknr(right_buffer), path->slots[1] + 1, 1); 1392aa5d6bedSChris Mason if (wret) 1393aa5d6bedSChris Mason ret = wret; 1394d6025579SChris Mason btrfs_mark_buffer_dirty(right_buffer); 1395d6025579SChris Mason btrfs_mark_buffer_dirty(l_buf); 1396eb60ceacSChris Mason BUG_ON(path->slots[0] != slot); 1397be0e5c09SChris Mason if (mid <= slot) { 1398234b63a0SChris Mason btrfs_block_release(root, path->nodes[0]); 1399eb60ceacSChris Mason path->nodes[0] = right_buffer; 1400be0e5c09SChris Mason path->slots[0] -= mid; 1401be0e5c09SChris Mason path->slots[1] += 1; 1402eb60ceacSChris Mason } else 1403234b63a0SChris Mason btrfs_block_release(root, right_buffer); 1404eb60ceacSChris Mason BUG_ON(path->slots[0] < 0); 1405098f59c2SChris Mason check_node(root, path, 1); 1406d4dbff95SChris Mason 1407d4dbff95SChris Mason if (!double_split) 1408d4dbff95SChris Mason return ret; 140931f3c99bSChris Mason right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr); 1410d4dbff95SChris Mason BUG_ON(!right_buffer); 1411d4dbff95SChris Mason right = btrfs_buffer_leaf(right_buffer); 1412d4dbff95SChris Mason memset(&right->header, 0, sizeof(right->header)); 14137eccb903SChris Mason btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); 1414d4dbff95SChris Mason btrfs_set_header_generation(&right->header, trans->transid); 14154d775673SChris Mason btrfs_set_header_owner(&right->header, root->root_key.objectid); 1416d4dbff95SChris Mason btrfs_set_header_level(&right->header, 0); 14173eb0314dSChris Mason memcpy(right->header.fsid, root->fs_info->disk_super->fsid, 14183eb0314dSChris Mason sizeof(right->header.fsid)); 1419d4dbff95SChris Mason btrfs_cpu_key_to_disk(&disk_key, ins_key); 1420d4dbff95SChris Mason btrfs_set_header_nritems(&right->header, 0); 1421d4dbff95SChris Mason wret = insert_ptr(trans, root, path, 1422d4dbff95SChris Mason &disk_key, 14237eccb903SChris Mason bh_blocknr(right_buffer), 1424d4dbff95SChris Mason path->slots[1], 1); 1425d4dbff95SChris Mason if (wret) 1426d4dbff95SChris Mason ret = wret; 1427a429e513SChris Mason if (path->slots[1] == 0) { 1428a429e513SChris Mason wret = fixup_low_keys(trans, root, path, &disk_key, 1); 1429a429e513SChris Mason if (wret) 1430a429e513SChris Mason ret = wret; 1431a429e513SChris Mason } 1432d4dbff95SChris Mason btrfs_block_release(root, path->nodes[0]); 1433d4dbff95SChris Mason path->nodes[0] = right_buffer; 1434d4dbff95SChris Mason path->slots[0] = 0; 1435d4dbff95SChris Mason check_node(root, path, 1); 1436d4dbff95SChris Mason check_leaf(root, path, 0); 1437be0e5c09SChris Mason return ret; 1438be0e5c09SChris Mason } 1439be0e5c09SChris Mason 1440b18c6685SChris Mason int btrfs_truncate_item(struct btrfs_trans_handle *trans, 1441b18c6685SChris Mason struct btrfs_root *root, 1442b18c6685SChris Mason struct btrfs_path *path, 1443b18c6685SChris Mason u32 new_size) 1444b18c6685SChris Mason { 1445b18c6685SChris Mason int ret = 0; 1446b18c6685SChris Mason int slot; 1447b18c6685SChris Mason int slot_orig; 1448b18c6685SChris Mason struct btrfs_leaf *leaf; 1449b18c6685SChris Mason struct buffer_head *leaf_buf; 1450b18c6685SChris Mason u32 nritems; 1451b18c6685SChris Mason unsigned int data_end; 1452b18c6685SChris Mason unsigned int old_data_start; 1453b18c6685SChris Mason unsigned int old_size; 1454b18c6685SChris Mason unsigned int size_diff; 1455b18c6685SChris Mason int i; 1456b18c6685SChris Mason 1457b18c6685SChris Mason slot_orig = path->slots[0]; 1458b18c6685SChris Mason leaf_buf = path->nodes[0]; 1459b18c6685SChris Mason leaf = btrfs_buffer_leaf(leaf_buf); 1460b18c6685SChris Mason 1461b18c6685SChris Mason nritems = btrfs_header_nritems(&leaf->header); 1462b18c6685SChris Mason data_end = leaf_data_end(root, leaf); 1463b18c6685SChris Mason 1464b18c6685SChris Mason slot = path->slots[0]; 1465b18c6685SChris Mason old_data_start = btrfs_item_offset(leaf->items + slot); 1466b18c6685SChris Mason old_size = btrfs_item_size(leaf->items + slot); 1467b18c6685SChris Mason BUG_ON(old_size <= new_size); 1468b18c6685SChris Mason size_diff = old_size - new_size; 1469b18c6685SChris Mason 1470b18c6685SChris Mason BUG_ON(slot < 0); 1471b18c6685SChris Mason BUG_ON(slot >= nritems); 1472b18c6685SChris Mason 1473b18c6685SChris Mason /* 1474b18c6685SChris Mason * item0..itemN ... dataN.offset..dataN.size .. data0.size 1475b18c6685SChris Mason */ 1476b18c6685SChris Mason /* first correct the data pointers */ 1477b18c6685SChris Mason for (i = slot; i < nritems; i++) { 1478b18c6685SChris Mason u32 ioff = btrfs_item_offset(leaf->items + i); 1479b18c6685SChris Mason btrfs_set_item_offset(leaf->items + i, 1480b18c6685SChris Mason ioff + size_diff); 1481b18c6685SChris Mason } 1482b18c6685SChris Mason /* shift the data */ 1483b18c6685SChris Mason btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + 1484b18c6685SChris Mason data_end + size_diff, btrfs_leaf_data(leaf) + 1485b18c6685SChris Mason data_end, old_data_start + new_size - data_end); 1486b18c6685SChris Mason btrfs_set_item_size(leaf->items + slot, new_size); 1487b18c6685SChris Mason btrfs_mark_buffer_dirty(leaf_buf); 1488b18c6685SChris Mason 1489b18c6685SChris Mason ret = 0; 1490b18c6685SChris Mason if (btrfs_leaf_free_space(root, leaf) < 0) 1491b18c6685SChris Mason BUG(); 1492b18c6685SChris Mason check_leaf(root, path, 0); 1493b18c6685SChris Mason return ret; 1494b18c6685SChris Mason } 1495b18c6685SChris Mason 14966567e837SChris Mason int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root 14976567e837SChris Mason *root, struct btrfs_path *path, u32 data_size) 14986567e837SChris Mason { 14996567e837SChris Mason int ret = 0; 15006567e837SChris Mason int slot; 15016567e837SChris Mason int slot_orig; 15026567e837SChris Mason struct btrfs_leaf *leaf; 15036567e837SChris Mason struct buffer_head *leaf_buf; 15046567e837SChris Mason u32 nritems; 15056567e837SChris Mason unsigned int data_end; 15066567e837SChris Mason unsigned int old_data; 15076567e837SChris Mason unsigned int old_size; 15086567e837SChris Mason int i; 15096567e837SChris Mason 15106567e837SChris Mason slot_orig = path->slots[0]; 15116567e837SChris Mason leaf_buf = path->nodes[0]; 15126567e837SChris Mason leaf = btrfs_buffer_leaf(leaf_buf); 15136567e837SChris Mason 15146567e837SChris Mason nritems = btrfs_header_nritems(&leaf->header); 15156567e837SChris Mason data_end = leaf_data_end(root, leaf); 15166567e837SChris Mason 15176567e837SChris Mason if (btrfs_leaf_free_space(root, leaf) < data_size) 15186567e837SChris Mason BUG(); 15196567e837SChris Mason slot = path->slots[0]; 15206567e837SChris Mason old_data = btrfs_item_end(leaf->items + slot); 15216567e837SChris Mason 15226567e837SChris Mason BUG_ON(slot < 0); 15236567e837SChris Mason BUG_ON(slot >= nritems); 15246567e837SChris Mason 15256567e837SChris Mason /* 15266567e837SChris Mason * item0..itemN ... dataN.offset..dataN.size .. data0.size 15276567e837SChris Mason */ 15286567e837SChris Mason /* first correct the data pointers */ 15296567e837SChris Mason for (i = slot; i < nritems; i++) { 15306567e837SChris Mason u32 ioff = btrfs_item_offset(leaf->items + i); 15316567e837SChris Mason btrfs_set_item_offset(leaf->items + i, 15326567e837SChris Mason ioff - data_size); 15336567e837SChris Mason } 15346567e837SChris Mason /* shift the data */ 15356567e837SChris Mason btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + 15366567e837SChris Mason data_end - data_size, btrfs_leaf_data(leaf) + 15376567e837SChris Mason data_end, old_data - data_end); 15386567e837SChris Mason data_end = old_data; 15396567e837SChris Mason old_size = btrfs_item_size(leaf->items + slot); 15406567e837SChris Mason btrfs_set_item_size(leaf->items + slot, old_size + data_size); 15416567e837SChris Mason btrfs_mark_buffer_dirty(leaf_buf); 15426567e837SChris Mason 15436567e837SChris Mason ret = 0; 15446567e837SChris Mason if (btrfs_leaf_free_space(root, leaf) < 0) 15456567e837SChris Mason BUG(); 15466567e837SChris Mason check_leaf(root, path, 0); 15476567e837SChris Mason return ret; 15486567e837SChris Mason } 15496567e837SChris Mason 155074123bd7SChris Mason /* 155174123bd7SChris Mason * Given a key and some data, insert an item into the tree. 155274123bd7SChris Mason * This does all the path init required, making room in the tree if needed. 155374123bd7SChris Mason */ 1554e089f05cSChris Mason int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root 1555e089f05cSChris Mason *root, struct btrfs_path *path, struct btrfs_key 1556e089f05cSChris Mason *cpu_key, u32 data_size) 1557be0e5c09SChris Mason { 1558aa5d6bedSChris Mason int ret = 0; 1559be0e5c09SChris Mason int slot; 1560eb60ceacSChris Mason int slot_orig; 1561234b63a0SChris Mason struct btrfs_leaf *leaf; 1562e20d96d6SChris Mason struct buffer_head *leaf_buf; 15637518a238SChris Mason u32 nritems; 1564be0e5c09SChris Mason unsigned int data_end; 1565e2fa7227SChris Mason struct btrfs_disk_key disk_key; 1566e2fa7227SChris Mason 1567e2fa7227SChris Mason btrfs_cpu_key_to_disk(&disk_key, cpu_key); 1568be0e5c09SChris Mason 156974123bd7SChris Mason /* create a root if there isn't one */ 15705c680ed6SChris Mason if (!root->node) 1571cfaa7295SChris Mason BUG(); 1572e089f05cSChris Mason ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); 1573eb60ceacSChris Mason if (ret == 0) { 1574f0930a37SChris Mason return -EEXIST; 1575aa5d6bedSChris Mason } 1576ed2ff2cbSChris Mason if (ret < 0) 1577ed2ff2cbSChris Mason goto out; 1578be0e5c09SChris Mason 157962e2749eSChris Mason slot_orig = path->slots[0]; 158062e2749eSChris Mason leaf_buf = path->nodes[0]; 1581e20d96d6SChris Mason leaf = btrfs_buffer_leaf(leaf_buf); 158274123bd7SChris Mason 15837518a238SChris Mason nritems = btrfs_header_nritems(&leaf->header); 1584123abc88SChris Mason data_end = leaf_data_end(root, leaf); 1585eb60ceacSChris Mason 1586123abc88SChris Mason if (btrfs_leaf_free_space(root, leaf) < 1587d4dbff95SChris Mason sizeof(struct btrfs_item) + data_size) { 1588be0e5c09SChris Mason BUG(); 1589d4dbff95SChris Mason } 159062e2749eSChris Mason slot = path->slots[0]; 1591eb60ceacSChris Mason BUG_ON(slot < 0); 1592be0e5c09SChris Mason if (slot != nritems) { 1593be0e5c09SChris Mason int i; 15940783fcfcSChris Mason unsigned int old_data = btrfs_item_end(leaf->items + slot); 1595be0e5c09SChris Mason 1596be0e5c09SChris Mason /* 1597be0e5c09SChris Mason * item0..itemN ... dataN.offset..dataN.size .. data0.size 1598be0e5c09SChris Mason */ 1599be0e5c09SChris Mason /* first correct the data pointers */ 16000783fcfcSChris Mason for (i = slot; i < nritems; i++) { 1601123abc88SChris Mason u32 ioff = btrfs_item_offset(leaf->items + i); 16020783fcfcSChris Mason btrfs_set_item_offset(leaf->items + i, 16030783fcfcSChris Mason ioff - data_size); 16040783fcfcSChris Mason } 1605be0e5c09SChris Mason 1606be0e5c09SChris Mason /* shift the items */ 1607d6025579SChris Mason btrfs_memmove(root, leaf, leaf->items + slot + 1, 1608d6025579SChris Mason leaf->items + slot, 16090783fcfcSChris Mason (nritems - slot) * sizeof(struct btrfs_item)); 1610be0e5c09SChris Mason 1611be0e5c09SChris Mason /* shift the data */ 1612d6025579SChris Mason btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + 1613d6025579SChris Mason data_end - data_size, btrfs_leaf_data(leaf) + 1614be0e5c09SChris Mason data_end, old_data - data_end); 1615be0e5c09SChris Mason data_end = old_data; 1616be0e5c09SChris Mason } 161762e2749eSChris Mason /* setup the item for the new data */ 1618d6025579SChris Mason btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key, 1619e2fa7227SChris Mason sizeof(struct btrfs_disk_key)); 16200783fcfcSChris Mason btrfs_set_item_offset(leaf->items + slot, data_end - data_size); 16210783fcfcSChris Mason btrfs_set_item_size(leaf->items + slot, data_size); 16227518a238SChris Mason btrfs_set_header_nritems(&leaf->header, nritems + 1); 1623d6025579SChris Mason btrfs_mark_buffer_dirty(leaf_buf); 1624aa5d6bedSChris Mason 1625aa5d6bedSChris Mason ret = 0; 16268e19f2cdSChris Mason if (slot == 0) 1627e089f05cSChris Mason ret = fixup_low_keys(trans, root, path, &disk_key, 1); 1628aa5d6bedSChris Mason 1629123abc88SChris Mason if (btrfs_leaf_free_space(root, leaf) < 0) 1630be0e5c09SChris Mason BUG(); 163162e2749eSChris Mason check_leaf(root, path, 0); 1632ed2ff2cbSChris Mason out: 163362e2749eSChris Mason return ret; 163462e2749eSChris Mason } 163562e2749eSChris Mason 163662e2749eSChris Mason /* 163762e2749eSChris Mason * Given a key and some data, insert an item into the tree. 163862e2749eSChris Mason * This does all the path init required, making room in the tree if needed. 163962e2749eSChris Mason */ 1640e089f05cSChris Mason int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root 1641e089f05cSChris Mason *root, struct btrfs_key *cpu_key, void *data, u32 1642e089f05cSChris Mason data_size) 164362e2749eSChris Mason { 164462e2749eSChris Mason int ret = 0; 16452c90e5d6SChris Mason struct btrfs_path *path; 164662e2749eSChris Mason u8 *ptr; 164762e2749eSChris Mason 16482c90e5d6SChris Mason path = btrfs_alloc_path(); 16492c90e5d6SChris Mason BUG_ON(!path); 16502c90e5d6SChris Mason btrfs_init_path(path); 16512c90e5d6SChris Mason ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); 165262e2749eSChris Mason if (!ret) { 16532c90e5d6SChris Mason ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), 16542c90e5d6SChris Mason path->slots[0], u8); 16552c90e5d6SChris Mason btrfs_memcpy(root, path->nodes[0]->b_data, 1656d6025579SChris Mason ptr, data, data_size); 16572c90e5d6SChris Mason btrfs_mark_buffer_dirty(path->nodes[0]); 165862e2749eSChris Mason } 16592c90e5d6SChris Mason btrfs_release_path(root, path); 16602c90e5d6SChris Mason btrfs_free_path(path); 1661aa5d6bedSChris Mason return ret; 1662be0e5c09SChris Mason } 1663be0e5c09SChris Mason 166474123bd7SChris Mason /* 16655de08d7dSChris Mason * delete the pointer from a given node. 166674123bd7SChris Mason * 166774123bd7SChris Mason * If the delete empties a node, the node is removed from the tree, 166874123bd7SChris Mason * continuing all the way the root if required. The root is converted into 166974123bd7SChris Mason * a leaf if all the nodes are emptied. 167074123bd7SChris Mason */ 1671e089f05cSChris Mason static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 1672e089f05cSChris Mason struct btrfs_path *path, int level, int slot) 1673be0e5c09SChris Mason { 1674234b63a0SChris Mason struct btrfs_node *node; 1675e20d96d6SChris Mason struct buffer_head *parent = path->nodes[level]; 16767518a238SChris Mason u32 nritems; 1677aa5d6bedSChris Mason int ret = 0; 1678bb803951SChris Mason int wret; 1679be0e5c09SChris Mason 1680e20d96d6SChris Mason node = btrfs_buffer_node(parent); 16817518a238SChris Mason nritems = btrfs_header_nritems(&node->header); 1682be0e5c09SChris Mason if (slot != nritems -1) { 1683d6025579SChris Mason btrfs_memmove(root, node, node->ptrs + slot, 1684d6025579SChris Mason node->ptrs + slot + 1, 1685d6025579SChris Mason sizeof(struct btrfs_key_ptr) * 1686d6025579SChris Mason (nritems - slot - 1)); 1687be0e5c09SChris Mason } 16887518a238SChris Mason nritems--; 16897518a238SChris Mason btrfs_set_header_nritems(&node->header, nritems); 16907518a238SChris Mason if (nritems == 0 && parent == root->node) { 1691e20d96d6SChris Mason struct btrfs_header *header = btrfs_buffer_header(root->node); 1692e20d96d6SChris Mason BUG_ON(btrfs_header_level(header) != 1); 1693eb60ceacSChris Mason /* just turn the root into a leaf and break */ 1694e20d96d6SChris Mason btrfs_set_header_level(header, 0); 1695bb803951SChris Mason } else if (slot == 0) { 1696e089f05cSChris Mason wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key, 1697123abc88SChris Mason level + 1); 16980f70abe2SChris Mason if (wret) 16990f70abe2SChris Mason ret = wret; 1700be0e5c09SChris Mason } 1701d6025579SChris Mason btrfs_mark_buffer_dirty(parent); 1702aa5d6bedSChris Mason return ret; 1703be0e5c09SChris Mason } 1704be0e5c09SChris Mason 170574123bd7SChris Mason /* 170674123bd7SChris Mason * delete the item at the leaf level in path. If that empties 170774123bd7SChris Mason * the leaf, remove it from the tree 170874123bd7SChris Mason */ 1709e089f05cSChris Mason int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, 1710e089f05cSChris Mason struct btrfs_path *path) 1711be0e5c09SChris Mason { 1712be0e5c09SChris Mason int slot; 1713234b63a0SChris Mason struct btrfs_leaf *leaf; 1714e20d96d6SChris Mason struct buffer_head *leaf_buf; 1715be0e5c09SChris Mason int doff; 1716be0e5c09SChris Mason int dsize; 1717aa5d6bedSChris Mason int ret = 0; 1718aa5d6bedSChris Mason int wret; 17197518a238SChris Mason u32 nritems; 1720be0e5c09SChris Mason 1721eb60ceacSChris Mason leaf_buf = path->nodes[0]; 1722e20d96d6SChris Mason leaf = btrfs_buffer_leaf(leaf_buf); 17234920c9acSChris Mason slot = path->slots[0]; 17240783fcfcSChris Mason doff = btrfs_item_offset(leaf->items + slot); 17250783fcfcSChris Mason dsize = btrfs_item_size(leaf->items + slot); 17267518a238SChris Mason nritems = btrfs_header_nritems(&leaf->header); 1727be0e5c09SChris Mason 17287518a238SChris Mason if (slot != nritems - 1) { 1729be0e5c09SChris Mason int i; 1730123abc88SChris Mason int data_end = leaf_data_end(root, leaf); 1731d6025579SChris Mason btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + 1732d6025579SChris Mason data_end + dsize, 1733123abc88SChris Mason btrfs_leaf_data(leaf) + data_end, 1734be0e5c09SChris Mason doff - data_end); 17350783fcfcSChris Mason for (i = slot + 1; i < nritems; i++) { 1736123abc88SChris Mason u32 ioff = btrfs_item_offset(leaf->items + i); 17370783fcfcSChris Mason btrfs_set_item_offset(leaf->items + i, ioff + dsize); 17380783fcfcSChris Mason } 1739d6025579SChris Mason btrfs_memmove(root, leaf, leaf->items + slot, 1740d6025579SChris Mason leaf->items + slot + 1, 17410783fcfcSChris Mason sizeof(struct btrfs_item) * 17427518a238SChris Mason (nritems - slot - 1)); 1743be0e5c09SChris Mason } 17447518a238SChris Mason btrfs_set_header_nritems(&leaf->header, nritems - 1); 17457518a238SChris Mason nritems--; 174674123bd7SChris Mason /* delete the leaf if we've emptied it */ 17477518a238SChris Mason if (nritems == 0) { 1748eb60ceacSChris Mason if (leaf_buf == root->node) { 17497518a238SChris Mason btrfs_set_header_level(&leaf->header, 0); 17509a8dd150SChris Mason } else { 1751e089f05cSChris Mason clean_tree_block(trans, root, leaf_buf); 1752d6025579SChris Mason wait_on_buffer(leaf_buf); 1753e089f05cSChris Mason wret = del_ptr(trans, root, path, 1, path->slots[1]); 1754aa5d6bedSChris Mason if (wret) 1755aa5d6bedSChris Mason ret = wret; 1756e089f05cSChris Mason wret = btrfs_free_extent(trans, root, 17577eccb903SChris Mason bh_blocknr(leaf_buf), 1, 1); 17580f70abe2SChris Mason if (wret) 17590f70abe2SChris Mason ret = wret; 17609a8dd150SChris Mason } 1761be0e5c09SChris Mason } else { 17627518a238SChris Mason int used = leaf_space_used(leaf, 0, nritems); 1763aa5d6bedSChris Mason if (slot == 0) { 1764e089f05cSChris Mason wret = fixup_low_keys(trans, root, path, 1765aa5d6bedSChris Mason &leaf->items[0].key, 1); 1766aa5d6bedSChris Mason if (wret) 1767aa5d6bedSChris Mason ret = wret; 1768aa5d6bedSChris Mason } 1769aa5d6bedSChris Mason 177074123bd7SChris Mason /* delete the leaf if it is mostly empty */ 1771123abc88SChris Mason if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { 1772be0e5c09SChris Mason /* push_leaf_left fixes the path. 1773be0e5c09SChris Mason * make sure the path still points to our leaf 1774be0e5c09SChris Mason * for possible call to del_ptr below 1775be0e5c09SChris Mason */ 17764920c9acSChris Mason slot = path->slots[1]; 1777e20d96d6SChris Mason get_bh(leaf_buf); 1778e089f05cSChris Mason wret = push_leaf_left(trans, root, path, 1); 1779aa5d6bedSChris Mason if (wret < 0) 1780aa5d6bedSChris Mason ret = wret; 1781f0930a37SChris Mason if (path->nodes[0] == leaf_buf && 17827518a238SChris Mason btrfs_header_nritems(&leaf->header)) { 1783e089f05cSChris Mason wret = push_leaf_right(trans, root, path, 1); 1784aa5d6bedSChris Mason if (wret < 0) 1785aa5d6bedSChris Mason ret = wret; 1786aa5d6bedSChris Mason } 17877518a238SChris Mason if (btrfs_header_nritems(&leaf->header) == 0) { 17887eccb903SChris Mason u64 blocknr = bh_blocknr(leaf_buf); 1789e089f05cSChris Mason clean_tree_block(trans, root, leaf_buf); 1790d6025579SChris Mason wait_on_buffer(leaf_buf); 1791e089f05cSChris Mason wret = del_ptr(trans, root, path, 1, slot); 1792aa5d6bedSChris Mason if (wret) 1793aa5d6bedSChris Mason ret = wret; 1794234b63a0SChris Mason btrfs_block_release(root, leaf_buf); 1795e089f05cSChris Mason wret = btrfs_free_extent(trans, root, blocknr, 1796e089f05cSChris Mason 1, 1); 17970f70abe2SChris Mason if (wret) 17980f70abe2SChris Mason ret = wret; 17995de08d7dSChris Mason } else { 1800d6025579SChris Mason btrfs_mark_buffer_dirty(leaf_buf); 1801234b63a0SChris Mason btrfs_block_release(root, leaf_buf); 1802be0e5c09SChris Mason } 1803d5719762SChris Mason } else { 1804d6025579SChris Mason btrfs_mark_buffer_dirty(leaf_buf); 1805be0e5c09SChris Mason } 18069a8dd150SChris Mason } 1807aa5d6bedSChris Mason return ret; 18089a8dd150SChris Mason } 18099a8dd150SChris Mason 181097571fd0SChris Mason /* 181197571fd0SChris Mason * walk up the tree as far as required to find the next leaf. 18120f70abe2SChris Mason * returns 0 if it found something or 1 if there are no greater leaves. 18130f70abe2SChris Mason * returns < 0 on io errors. 181497571fd0SChris Mason */ 1815234b63a0SChris Mason int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) 1816d97e63b6SChris Mason { 1817d97e63b6SChris Mason int slot; 1818d97e63b6SChris Mason int level = 1; 1819d97e63b6SChris Mason u64 blocknr; 1820e20d96d6SChris Mason struct buffer_head *c; 1821e20d96d6SChris Mason struct btrfs_node *c_node; 1822e20d96d6SChris Mason struct buffer_head *next = NULL; 1823d97e63b6SChris Mason 1824234b63a0SChris Mason while(level < BTRFS_MAX_LEVEL) { 1825d97e63b6SChris Mason if (!path->nodes[level]) 18260f70abe2SChris Mason return 1; 1827d97e63b6SChris Mason slot = path->slots[level] + 1; 1828d97e63b6SChris Mason c = path->nodes[level]; 1829e20d96d6SChris Mason c_node = btrfs_buffer_node(c); 1830e20d96d6SChris Mason if (slot >= btrfs_header_nritems(&c_node->header)) { 1831d97e63b6SChris Mason level++; 1832d97e63b6SChris Mason continue; 1833d97e63b6SChris Mason } 1834e20d96d6SChris Mason blocknr = btrfs_node_blockptr(c_node, slot); 1835cfaa7295SChris Mason if (next) 1836234b63a0SChris Mason btrfs_block_release(root, next); 1837d97e63b6SChris Mason next = read_tree_block(root, blocknr); 1838d97e63b6SChris Mason break; 1839d97e63b6SChris Mason } 1840d97e63b6SChris Mason path->slots[level] = slot; 1841d97e63b6SChris Mason while(1) { 1842d97e63b6SChris Mason level--; 1843d97e63b6SChris Mason c = path->nodes[level]; 1844234b63a0SChris Mason btrfs_block_release(root, c); 1845d97e63b6SChris Mason path->nodes[level] = next; 1846d97e63b6SChris Mason path->slots[level] = 0; 1847d97e63b6SChris Mason if (!level) 1848d97e63b6SChris Mason break; 18491d4f8a0cSChris Mason next = read_tree_block(root, 1850e20d96d6SChris Mason btrfs_node_blockptr(btrfs_buffer_node(next), 0)); 1851d97e63b6SChris Mason } 1852d97e63b6SChris Mason return 0; 1853d97e63b6SChris Mason } 1854