blob: aa824e2c521fcda2f4f8333a6e78556f53d941d2 [file] [log] [blame]
Chris Mason6cbd5572007-06-12 09:07:21 -04001/*
2 * Copyright (C) 2007 Oracle. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
17 */
18
Chris Masoneb60cea2007-02-02 09:18:22 -050019#include "ctree.h"
20#include "disk-io.h"
Chris Mason7f5c1512007-03-23 15:56:19 -040021#include "transaction.h"
Chris Mason9a8dd152007-02-23 08:38:36 -050022
Chris Masone089f052007-03-16 16:20:31 -040023static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
24 *root, struct btrfs_path *path, int level);
25static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masond4dbff92007-04-04 14:08:15 -040026 *root, struct btrfs_key *ins_key,
27 struct btrfs_path *path, int data_size);
Chris Masone089f052007-03-16 16:20:31 -040028static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masone20d96d2007-03-22 12:13:20 -040029 *root, struct buffer_head *dst, struct buffer_head
Chris Masone089f052007-03-16 16:20:31 -040030 *src);
31static int balance_node_right(struct btrfs_trans_handle *trans, struct
Chris Masone20d96d2007-03-22 12:13:20 -040032 btrfs_root *root, struct buffer_head *dst_buf,
33 struct buffer_head *src_buf);
Chris Masone089f052007-03-16 16:20:31 -040034static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
35 struct btrfs_path *path, int level, int slot);
Chris Masond97e63b2007-02-20 16:40:44 -050036
Chris Masondf24a2b2007-04-04 09:36:31 -040037inline void btrfs_init_path(struct btrfs_path *p)
38{
39 memset(p, 0, sizeof(*p));
40}
41
Chris Mason2c90e5d2007-04-02 10:50:19 -040042struct btrfs_path *btrfs_alloc_path(void)
43{
Chris Masondf24a2b2007-04-04 09:36:31 -040044 struct btrfs_path *path;
45 path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
46 if (path)
47 btrfs_init_path(path);
48 return path;
Chris Mason2c90e5d2007-04-02 10:50:19 -040049}
50
51void btrfs_free_path(struct btrfs_path *p)
52{
Chris Masondf24a2b2007-04-04 09:36:31 -040053 btrfs_release_path(NULL, p);
Chris Mason2c90e5d2007-04-02 10:50:19 -040054 kmem_cache_free(btrfs_path_cachep, p);
55}
56
Chris Mason234b63a2007-03-13 10:46:10 -040057void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
Chris Masoneb60cea2007-02-02 09:18:22 -050058{
59 int i;
Chris Mason234b63a2007-03-13 10:46:10 -040060 for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
Chris Masoneb60cea2007-02-02 09:18:22 -050061 if (!p->nodes[i])
62 break;
Chris Mason234b63a2007-03-13 10:46:10 -040063 btrfs_block_release(root, p->nodes[i]);
Chris Masoneb60cea2007-02-02 09:18:22 -050064 }
Chris Masonaa5d6be2007-02-28 16:35:06 -050065 memset(p, 0, sizeof(*p));
Chris Masoneb60cea2007-02-02 09:18:22 -050066}
67
Chris Masone089f052007-03-16 16:20:31 -040068static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masone20d96d2007-03-22 12:13:20 -040069 *root, struct buffer_head *buf, struct buffer_head
70 *parent, int parent_slot, struct buffer_head
Chris Masone089f052007-03-16 16:20:31 -040071 **cow_ret)
Chris Mason02217ed2007-03-02 16:08:05 -050072{
Chris Masone20d96d2007-03-22 12:13:20 -040073 struct buffer_head *cow;
74 struct btrfs_node *cow_node;
Chris Mason54aa1f42007-06-22 14:16:25 -040075 int ret;
Chris Mason02217ed2007-03-02 16:08:05 -050076
Chris Masonccd467d2007-06-28 15:57:36 -040077 WARN_ON(!buffer_uptodate(buf));
78 if (trans->transaction != root->fs_info->running_transaction) {
79 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
80 root->fs_info->running_transaction->transid);
81 WARN_ON(1);
82 }
83 if (trans->transid != root->fs_info->generation) {
84 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
85 root->fs_info->generation);
86 WARN_ON(1);
87 }
Chris Mason7f5c1512007-03-23 15:56:19 -040088 if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
89 trans->transid) {
Chris Mason02217ed2007-03-02 16:08:05 -050090 *cow_ret = buf;
91 return 0;
92 }
Chris Mason31f3c992007-04-30 15:25:45 -040093 cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr);
Chris Mason54aa1f42007-06-22 14:16:25 -040094 if (IS_ERR(cow))
95 return PTR_ERR(cow);
Chris Masone20d96d2007-03-22 12:13:20 -040096 cow_node = btrfs_buffer_node(cow);
Chris Mason2c90e5d2007-04-02 10:50:19 -040097 if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
98 WARN_ON(1);
Chris Masone20d96d2007-03-22 12:13:20 -040099 memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
Chris Mason7eccb902007-04-11 15:53:25 -0400100 btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow));
Chris Mason7f5c1512007-03-23 15:56:19 -0400101 btrfs_set_header_generation(&cow_node->header, trans->transid);
Chris Mason4d775672007-04-20 20:23:12 -0400102 btrfs_set_header_owner(&cow_node->header, root->root_key.objectid);
Chris Mason54aa1f42007-06-22 14:16:25 -0400103 ret = btrfs_inc_ref(trans, root, buf);
104 if (ret)
105 return ret;
Chris Mason02217ed2007-03-02 16:08:05 -0500106 if (buf == root->node) {
107 root->node = cow;
Chris Masone20d96d2007-03-22 12:13:20 -0400108 get_bh(cow);
Chris Mason2c90e5d2007-04-02 10:50:19 -0400109 if (buf != root->commit_root) {
Chris Mason7eccb902007-04-11 15:53:25 -0400110 btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
Chris Mason2c90e5d2007-04-02 10:50:19 -0400111 }
Chris Mason234b63a2007-03-13 10:46:10 -0400112 btrfs_block_release(root, buf);
Chris Mason02217ed2007-03-02 16:08:05 -0500113 } else {
Chris Masone20d96d2007-03-22 12:13:20 -0400114 btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
Chris Mason7eccb902007-04-11 15:53:25 -0400115 bh_blocknr(cow));
Chris Masond6025572007-03-30 14:27:56 -0400116 btrfs_mark_buffer_dirty(parent);
Chris Mason7eccb902007-04-11 15:53:25 -0400117 btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
Chris Mason02217ed2007-03-02 16:08:05 -0500118 }
Chris Mason234b63a2007-03-13 10:46:10 -0400119 btrfs_block_release(root, buf);
Chris Masonccd467d2007-06-28 15:57:36 -0400120 btrfs_mark_buffer_dirty(cow);
Chris Mason2c90e5d2007-04-02 10:50:19 -0400121 *cow_ret = cow;
Chris Mason02217ed2007-03-02 16:08:05 -0500122 return 0;
123}
124
Chris Mason74123bd2007-02-02 11:05:29 -0500125/*
126 * The leaf data grows from end-to-front in the node.
127 * this returns the address of the start of the last item,
128 * which is the stop of the leaf data stack
129 */
Chris Mason123abc82007-03-14 14:14:43 -0400130static inline unsigned int leaf_data_end(struct btrfs_root *root,
131 struct btrfs_leaf *leaf)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500132{
Chris Mason7518a232007-03-12 12:01:18 -0400133 u32 nr = btrfs_header_nritems(&leaf->header);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500134 if (nr == 0)
Chris Mason123abc82007-03-14 14:14:43 -0400135 return BTRFS_LEAF_DATA_SIZE(root);
Chris Mason0783fcf2007-03-12 20:12:07 -0400136 return btrfs_item_offset(leaf->items + nr - 1);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500137}
138
Chris Mason74123bd2007-02-02 11:05:29 -0500139/*
Chris Mason74123bd2007-02-02 11:05:29 -0500140 * compare two keys in a memcmp fashion
141 */
Chris Mason9aca1d52007-03-13 11:09:37 -0400142static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500143{
Chris Masone2fa7222007-03-12 16:22:34 -0400144 struct btrfs_key k1;
145
146 btrfs_disk_key_to_cpu(&k1, disk);
147
148 if (k1.objectid > k2->objectid)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500149 return 1;
Chris Masone2fa7222007-03-12 16:22:34 -0400150 if (k1.objectid < k2->objectid)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500151 return -1;
Chris Masonf254e522007-03-29 15:15:27 -0400152 if (k1.flags > k2->flags)
153 return 1;
154 if (k1.flags < k2->flags)
155 return -1;
Chris Mason70b2bef2007-04-17 15:39:32 -0400156 if (k1.offset > k2->offset)
157 return 1;
158 if (k1.offset < k2->offset)
159 return -1;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500160 return 0;
161}
Chris Mason74123bd2007-02-02 11:05:29 -0500162
Chris Mason123abc82007-03-14 14:14:43 -0400163static int check_node(struct btrfs_root *root, struct btrfs_path *path,
164 int level)
Chris Masonaa5d6be2007-02-28 16:35:06 -0500165{
Chris Mason234b63a2007-03-13 10:46:10 -0400166 struct btrfs_node *parent = NULL;
Chris Masone20d96d2007-03-22 12:13:20 -0400167 struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500168 int parent_slot;
Chris Mason8d7be552007-05-10 11:24:42 -0400169 int slot;
170 struct btrfs_key cpukey;
Chris Mason7518a232007-03-12 12:01:18 -0400171 u32 nritems = btrfs_header_nritems(&node->header);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500172
173 if (path->nodes[level + 1])
Chris Masone20d96d2007-03-22 12:13:20 -0400174 parent = btrfs_buffer_node(path->nodes[level + 1]);
Aneesha1f396302007-07-11 10:03:27 -0400175
Chris Mason8d7be552007-05-10 11:24:42 -0400176 slot = path->slots[level];
Chris Mason7518a232007-03-12 12:01:18 -0400177 BUG_ON(nritems == 0);
178 if (parent) {
Chris Masone2fa7222007-03-12 16:22:34 -0400179 struct btrfs_disk_key *parent_key;
Aneesha1f396302007-07-11 10:03:27 -0400180
181 parent_slot = path->slots[level + 1];
Chris Mason123abc82007-03-14 14:14:43 -0400182 parent_key = &parent->ptrs[parent_slot].key;
183 BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
Chris Masone2fa7222007-03-12 16:22:34 -0400184 sizeof(struct btrfs_disk_key)));
Chris Mason1d4f8a02007-03-13 09:28:32 -0400185 BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
Chris Mason7518a232007-03-12 12:01:18 -0400186 btrfs_header_blocknr(&node->header));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500187 }
Chris Mason123abc82007-03-14 14:14:43 -0400188 BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
Chris Mason8d7be552007-05-10 11:24:42 -0400189 if (slot != 0) {
190 btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot - 1].key);
191 BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) <= 0);
192 }
193 if (slot < nritems - 1) {
194 btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot + 1].key);
195 BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) >= 0);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500196 }
197 return 0;
198}
199
Chris Mason123abc82007-03-14 14:14:43 -0400200static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
201 int level)
Chris Masonaa5d6be2007-02-28 16:35:06 -0500202{
Chris Masone20d96d2007-03-22 12:13:20 -0400203 struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
Chris Mason234b63a2007-03-13 10:46:10 -0400204 struct btrfs_node *parent = NULL;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500205 int parent_slot;
Chris Mason8d7be552007-05-10 11:24:42 -0400206 int slot = path->slots[0];
207 struct btrfs_key cpukey;
208
Chris Mason7518a232007-03-12 12:01:18 -0400209 u32 nritems = btrfs_header_nritems(&leaf->header);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500210
211 if (path->nodes[level + 1])
Chris Masone20d96d2007-03-22 12:13:20 -0400212 parent = btrfs_buffer_node(path->nodes[level + 1]);
Aneesha1f396302007-07-11 10:03:27 -0400213
Chris Mason123abc82007-03-14 14:14:43 -0400214 BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
Chris Mason7518a232007-03-12 12:01:18 -0400215
216 if (nritems == 0)
217 return 0;
218
219 if (parent) {
Chris Masone2fa7222007-03-12 16:22:34 -0400220 struct btrfs_disk_key *parent_key;
Aneesha1f396302007-07-11 10:03:27 -0400221
222 parent_slot = path->slots[level + 1];
Chris Mason123abc82007-03-14 14:14:43 -0400223 parent_key = &parent->ptrs[parent_slot].key;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500224 BUG_ON(memcmp(parent_key, &leaf->items[0].key,
Chris Masone2fa7222007-03-12 16:22:34 -0400225 sizeof(struct btrfs_disk_key)));
Chris Mason1d4f8a02007-03-13 09:28:32 -0400226 BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
Chris Mason7518a232007-03-12 12:01:18 -0400227 btrfs_header_blocknr(&leaf->header));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500228 }
Chris Mason8d7be552007-05-10 11:24:42 -0400229 if (slot != 0) {
230 btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot - 1].key);
231 BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) <= 0);
232 BUG_ON(btrfs_item_offset(leaf->items + slot - 1) !=
233 btrfs_item_end(leaf->items + slot));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500234 }
Chris Mason8d7be552007-05-10 11:24:42 -0400235 if (slot < nritems - 1) {
236 btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot + 1].key);
237 BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) >= 0);
238 BUG_ON(btrfs_item_offset(leaf->items + slot) !=
239 btrfs_item_end(leaf->items + slot + 1));
240 }
241 BUG_ON(btrfs_item_offset(leaf->items) +
242 btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500243 return 0;
244}
245
Chris Mason123abc82007-03-14 14:14:43 -0400246static int check_block(struct btrfs_root *root, struct btrfs_path *path,
247 int level)
Chris Masonaa5d6be2007-02-28 16:35:06 -0500248{
Chris Mason3eb03142007-04-05 14:28:50 -0400249 struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
250 if (memcmp(node->header.fsid, root->fs_info->disk_super->fsid,
251 sizeof(node->header.fsid)))
252 BUG();
Chris Masonaa5d6be2007-02-28 16:35:06 -0500253 if (level == 0)
Chris Mason123abc82007-03-14 14:14:43 -0400254 return check_leaf(root, path, level);
255 return check_node(root, path, level);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500256}
257
Chris Mason74123bd2007-02-02 11:05:29 -0500258/*
259 * search for key in the array p. items p are item_size apart
260 * and there are 'max' items in p
261 * the slot in the array is returned via slot, and it points to
262 * the place where you would insert key if it is not found in
263 * the array.
264 *
265 * slot may point to max if the key is bigger than all of the keys
266 */
Chris Mason9aca1d52007-03-13 11:09:37 -0400267static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
Chris Masonbe0e5c02007-01-26 15:51:26 -0500268 int max, int *slot)
269{
270 int low = 0;
271 int high = max;
272 int mid;
273 int ret;
Chris Masone2fa7222007-03-12 16:22:34 -0400274 struct btrfs_disk_key *tmp;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500275
276 while(low < high) {
277 mid = (low + high) / 2;
Chris Masone2fa7222007-03-12 16:22:34 -0400278 tmp = (struct btrfs_disk_key *)(p + mid * item_size);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500279 ret = comp_keys(tmp, key);
280
281 if (ret < 0)
282 low = mid + 1;
283 else if (ret > 0)
284 high = mid;
285 else {
286 *slot = mid;
287 return 0;
288 }
289 }
290 *slot = low;
291 return 1;
292}
293
Chris Mason97571fd2007-02-24 13:39:08 -0500294/*
295 * simple bin_search frontend that does the right thing for
296 * leaves vs nodes
297 */
Chris Mason9aca1d52007-03-13 11:09:37 -0400298static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500299{
Chris Mason7518a232007-03-12 12:01:18 -0400300 if (btrfs_is_leaf(c)) {
Chris Mason234b63a2007-03-13 10:46:10 -0400301 struct btrfs_leaf *l = (struct btrfs_leaf *)c;
Chris Mason0783fcf2007-03-12 20:12:07 -0400302 return generic_bin_search((void *)l->items,
303 sizeof(struct btrfs_item),
Chris Mason7518a232007-03-12 12:01:18 -0400304 key, btrfs_header_nritems(&c->header),
305 slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500306 } else {
Chris Mason123abc82007-03-14 14:14:43 -0400307 return generic_bin_search((void *)c->ptrs,
308 sizeof(struct btrfs_key_ptr),
Chris Mason7518a232007-03-12 12:01:18 -0400309 key, btrfs_header_nritems(&c->header),
310 slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500311 }
312 return -1;
313}
314
Chris Masone20d96d2007-03-22 12:13:20 -0400315static struct buffer_head *read_node_slot(struct btrfs_root *root,
316 struct buffer_head *parent_buf,
Chris Masonbb803952007-03-01 12:04:21 -0500317 int slot)
318{
Chris Masone20d96d2007-03-22 12:13:20 -0400319 struct btrfs_node *node = btrfs_buffer_node(parent_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500320 if (slot < 0)
321 return NULL;
Chris Mason7518a232007-03-12 12:01:18 -0400322 if (slot >= btrfs_header_nritems(&node->header))
Chris Masonbb803952007-03-01 12:04:21 -0500323 return NULL;
Chris Mason1d4f8a02007-03-13 09:28:32 -0400324 return read_tree_block(root, btrfs_node_blockptr(node, slot));
Chris Masonbb803952007-03-01 12:04:21 -0500325}
326
Chris Masone089f052007-03-16 16:20:31 -0400327static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
328 *root, struct btrfs_path *path, int level)
Chris Masonbb803952007-03-01 12:04:21 -0500329{
Chris Masone20d96d2007-03-22 12:13:20 -0400330 struct buffer_head *right_buf;
331 struct buffer_head *mid_buf;
332 struct buffer_head *left_buf;
333 struct buffer_head *parent_buf = NULL;
Chris Mason234b63a2007-03-13 10:46:10 -0400334 struct btrfs_node *right = NULL;
335 struct btrfs_node *mid;
336 struct btrfs_node *left = NULL;
337 struct btrfs_node *parent = NULL;
Chris Masonbb803952007-03-01 12:04:21 -0500338 int ret = 0;
339 int wret;
340 int pslot;
Chris Masonbb803952007-03-01 12:04:21 -0500341 int orig_slot = path->slots[level];
Chris Mason54aa1f42007-06-22 14:16:25 -0400342 int err_on_enospc = 0;
Chris Mason79f95c82007-03-01 15:16:26 -0500343 u64 orig_ptr;
Chris Masonbb803952007-03-01 12:04:21 -0500344
345 if (level == 0)
346 return 0;
347
348 mid_buf = path->nodes[level];
Chris Masone20d96d2007-03-22 12:13:20 -0400349 mid = btrfs_buffer_node(mid_buf);
Chris Mason1d4f8a02007-03-13 09:28:32 -0400350 orig_ptr = btrfs_node_blockptr(mid, orig_slot);
Chris Mason79f95c82007-03-01 15:16:26 -0500351
Chris Mason234b63a2007-03-13 10:46:10 -0400352 if (level < BTRFS_MAX_LEVEL - 1)
Chris Masonbb803952007-03-01 12:04:21 -0500353 parent_buf = path->nodes[level + 1];
354 pslot = path->slots[level + 1];
355
Chris Mason40689472007-03-17 14:29:23 -0400356 /*
357 * deal with the case where there is only one pointer in the root
358 * by promoting the node below to a root
359 */
Chris Masonbb803952007-03-01 12:04:21 -0500360 if (!parent_buf) {
Chris Masone20d96d2007-03-22 12:13:20 -0400361 struct buffer_head *child;
Chris Mason7eccb902007-04-11 15:53:25 -0400362 u64 blocknr = bh_blocknr(mid_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500363
Chris Mason7518a232007-03-12 12:01:18 -0400364 if (btrfs_header_nritems(&mid->header) != 1)
Chris Masonbb803952007-03-01 12:04:21 -0500365 return 0;
366
367 /* promote the child to a root */
368 child = read_node_slot(root, mid_buf, 0);
369 BUG_ON(!child);
370 root->node = child;
371 path->nodes[level] = NULL;
Chris Masond6025572007-03-30 14:27:56 -0400372 clean_tree_block(trans, root, mid_buf);
373 wait_on_buffer(mid_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500374 /* once for the path */
Chris Mason234b63a2007-03-13 10:46:10 -0400375 btrfs_block_release(root, mid_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500376 /* once for the root ptr */
Chris Mason234b63a2007-03-13 10:46:10 -0400377 btrfs_block_release(root, mid_buf);
Chris Masone089f052007-03-16 16:20:31 -0400378 return btrfs_free_extent(trans, root, blocknr, 1, 1);
Chris Masonbb803952007-03-01 12:04:21 -0500379 }
Chris Masone20d96d2007-03-22 12:13:20 -0400380 parent = btrfs_buffer_node(parent_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500381
Chris Mason123abc82007-03-14 14:14:43 -0400382 if (btrfs_header_nritems(&mid->header) >
383 BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
Chris Masonbb803952007-03-01 12:04:21 -0500384 return 0;
385
Chris Mason54aa1f42007-06-22 14:16:25 -0400386 if (btrfs_header_nritems(&mid->header) < 2)
387 err_on_enospc = 1;
388
Chris Masonbb803952007-03-01 12:04:21 -0500389 left_buf = read_node_slot(root, parent_buf, pslot - 1);
390 right_buf = read_node_slot(root, parent_buf, pslot + 1);
Chris Mason79f95c82007-03-01 15:16:26 -0500391
392 /* first, try to make some room in the middle buffer */
Chris Masonbb803952007-03-01 12:04:21 -0500393 if (left_buf) {
Chris Mason54aa1f42007-06-22 14:16:25 -0400394 wret = btrfs_cow_block(trans, root, left_buf,
395 parent_buf, pslot - 1, &left_buf);
396 if (wret) {
397 ret = wret;
398 goto enospc;
399 }
Chris Masone20d96d2007-03-22 12:13:20 -0400400 left = btrfs_buffer_node(left_buf);
Chris Mason7518a232007-03-12 12:01:18 -0400401 orig_slot += btrfs_header_nritems(&left->header);
Chris Masone089f052007-03-16 16:20:31 -0400402 wret = push_node_left(trans, root, left_buf, mid_buf);
Chris Mason79f95c82007-03-01 15:16:26 -0500403 if (wret < 0)
404 ret = wret;
Chris Mason54aa1f42007-06-22 14:16:25 -0400405 if (btrfs_header_nritems(&mid->header) < 2)
406 err_on_enospc = 1;
Chris Masonbb803952007-03-01 12:04:21 -0500407 }
Chris Mason79f95c82007-03-01 15:16:26 -0500408
409 /*
410 * then try to empty the right most buffer into the middle
411 */
Chris Masonbb803952007-03-01 12:04:21 -0500412 if (right_buf) {
Chris Mason54aa1f42007-06-22 14:16:25 -0400413 wret = btrfs_cow_block(trans, root, right_buf,
414 parent_buf, pslot + 1, &right_buf);
415 if (wret) {
416 ret = wret;
417 goto enospc;
418 }
419
Chris Masone20d96d2007-03-22 12:13:20 -0400420 right = btrfs_buffer_node(right_buf);
Chris Masone089f052007-03-16 16:20:31 -0400421 wret = push_node_left(trans, root, mid_buf, right_buf);
Chris Mason54aa1f42007-06-22 14:16:25 -0400422 if (wret < 0 && wret != -ENOSPC)
Chris Mason79f95c82007-03-01 15:16:26 -0500423 ret = wret;
Chris Mason7518a232007-03-12 12:01:18 -0400424 if (btrfs_header_nritems(&right->header) == 0) {
Chris Mason7eccb902007-04-11 15:53:25 -0400425 u64 blocknr = bh_blocknr(right_buf);
Chris Masone089f052007-03-16 16:20:31 -0400426 clean_tree_block(trans, root, right_buf);
Chris Masond6025572007-03-30 14:27:56 -0400427 wait_on_buffer(right_buf);
428 btrfs_block_release(root, right_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500429 right_buf = NULL;
430 right = NULL;
Chris Masone089f052007-03-16 16:20:31 -0400431 wret = del_ptr(trans, root, path, level + 1, pslot +
432 1);
Chris Masonbb803952007-03-01 12:04:21 -0500433 if (wret)
434 ret = wret;
Chris Masone089f052007-03-16 16:20:31 -0400435 wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
Chris Masonbb803952007-03-01 12:04:21 -0500436 if (wret)
437 ret = wret;
438 } else {
Chris Masond6025572007-03-30 14:27:56 -0400439 btrfs_memcpy(root, parent,
440 &parent->ptrs[pslot + 1].key,
441 &right->ptrs[0].key,
442 sizeof(struct btrfs_disk_key));
443 btrfs_mark_buffer_dirty(parent_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500444 }
445 }
Chris Mason7518a232007-03-12 12:01:18 -0400446 if (btrfs_header_nritems(&mid->header) == 1) {
Chris Mason79f95c82007-03-01 15:16:26 -0500447 /*
448 * we're not allowed to leave a node with one item in the
449 * tree during a delete. A deletion from lower in the tree
450 * could try to delete the only pointer in this node.
451 * So, pull some keys from the left.
452 * There has to be a left pointer at this point because
453 * otherwise we would have pulled some pointers from the
454 * right
455 */
456 BUG_ON(!left_buf);
Chris Masone089f052007-03-16 16:20:31 -0400457 wret = balance_node_right(trans, root, mid_buf, left_buf);
Chris Mason54aa1f42007-06-22 14:16:25 -0400458 if (wret < 0) {
Chris Mason79f95c82007-03-01 15:16:26 -0500459 ret = wret;
Chris Mason54aa1f42007-06-22 14:16:25 -0400460 goto enospc;
461 }
Chris Mason79f95c82007-03-01 15:16:26 -0500462 BUG_ON(wret == 1);
463 }
Chris Mason7518a232007-03-12 12:01:18 -0400464 if (btrfs_header_nritems(&mid->header) == 0) {
Chris Mason79f95c82007-03-01 15:16:26 -0500465 /* we've managed to empty the middle node, drop it */
Chris Mason7eccb902007-04-11 15:53:25 -0400466 u64 blocknr = bh_blocknr(mid_buf);
Chris Masone089f052007-03-16 16:20:31 -0400467 clean_tree_block(trans, root, mid_buf);
Chris Masond6025572007-03-30 14:27:56 -0400468 wait_on_buffer(mid_buf);
469 btrfs_block_release(root, mid_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500470 mid_buf = NULL;
471 mid = NULL;
Chris Masone089f052007-03-16 16:20:31 -0400472 wret = del_ptr(trans, root, path, level + 1, pslot);
Chris Masonbb803952007-03-01 12:04:21 -0500473 if (wret)
474 ret = wret;
Chris Masone089f052007-03-16 16:20:31 -0400475 wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
Chris Masonbb803952007-03-01 12:04:21 -0500476 if (wret)
477 ret = wret;
Chris Mason79f95c82007-03-01 15:16:26 -0500478 } else {
479 /* update the parent key to reflect our changes */
Chris Masond6025572007-03-30 14:27:56 -0400480 btrfs_memcpy(root, parent,
481 &parent->ptrs[pslot].key, &mid->ptrs[0].key,
482 sizeof(struct btrfs_disk_key));
483 btrfs_mark_buffer_dirty(parent_buf);
Chris Mason79f95c82007-03-01 15:16:26 -0500484 }
Chris Masonbb803952007-03-01 12:04:21 -0500485
Chris Mason79f95c82007-03-01 15:16:26 -0500486 /* update the path */
Chris Masonbb803952007-03-01 12:04:21 -0500487 if (left_buf) {
Chris Mason7518a232007-03-12 12:01:18 -0400488 if (btrfs_header_nritems(&left->header) > orig_slot) {
Chris Masone20d96d2007-03-22 12:13:20 -0400489 get_bh(left_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500490 path->nodes[level] = left_buf;
491 path->slots[level + 1] -= 1;
492 path->slots[level] = orig_slot;
493 if (mid_buf)
Chris Mason234b63a2007-03-13 10:46:10 -0400494 btrfs_block_release(root, mid_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500495 } else {
Chris Mason7518a232007-03-12 12:01:18 -0400496 orig_slot -= btrfs_header_nritems(&left->header);
Chris Masonbb803952007-03-01 12:04:21 -0500497 path->slots[level] = orig_slot;
498 }
499 }
Chris Mason79f95c82007-03-01 15:16:26 -0500500 /* double check we haven't messed things up */
Chris Mason123abc82007-03-14 14:14:43 -0400501 check_block(root, path, level);
Chris Masone20d96d2007-03-22 12:13:20 -0400502 if (orig_ptr !=
503 btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
504 path->slots[level]))
Chris Mason79f95c82007-03-01 15:16:26 -0500505 BUG();
Chris Mason54aa1f42007-06-22 14:16:25 -0400506enospc:
Chris Masonbb803952007-03-01 12:04:21 -0500507 if (right_buf)
Chris Mason234b63a2007-03-13 10:46:10 -0400508 btrfs_block_release(root, right_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500509 if (left_buf)
Chris Mason234b63a2007-03-13 10:46:10 -0400510 btrfs_block_release(root, left_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500511 return ret;
512}
513
Chris Masone66f7092007-04-20 13:16:02 -0400514/* returns zero if the push worked, non-zero otherwise */
515static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
516 struct btrfs_root *root,
517 struct btrfs_path *path, int level)
518{
519 struct buffer_head *right_buf;
520 struct buffer_head *mid_buf;
521 struct buffer_head *left_buf;
522 struct buffer_head *parent_buf = NULL;
523 struct btrfs_node *right = NULL;
524 struct btrfs_node *mid;
525 struct btrfs_node *left = NULL;
526 struct btrfs_node *parent = NULL;
527 int ret = 0;
528 int wret;
529 int pslot;
530 int orig_slot = path->slots[level];
531 u64 orig_ptr;
532
533 if (level == 0)
534 return 1;
535
536 mid_buf = path->nodes[level];
537 mid = btrfs_buffer_node(mid_buf);
538 orig_ptr = btrfs_node_blockptr(mid, orig_slot);
539
540 if (level < BTRFS_MAX_LEVEL - 1)
541 parent_buf = path->nodes[level + 1];
542 pslot = path->slots[level + 1];
543
544 if (!parent_buf)
545 return 1;
546 parent = btrfs_buffer_node(parent_buf);
547
548 left_buf = read_node_slot(root, parent_buf, pslot - 1);
549
550 /* first, try to make some room in the middle buffer */
551 if (left_buf) {
552 u32 left_nr;
Chris Masone66f7092007-04-20 13:16:02 -0400553 left = btrfs_buffer_node(left_buf);
554 left_nr = btrfs_header_nritems(&left->header);
Chris Mason33ade1f2007-04-20 13:48:57 -0400555 if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
556 wret = 1;
557 } else {
Chris Mason54aa1f42007-06-22 14:16:25 -0400558 ret = btrfs_cow_block(trans, root, left_buf, parent_buf,
559 pslot - 1, &left_buf);
560 if (ret)
561 wret = 1;
562 else {
563 left = btrfs_buffer_node(left_buf);
564 wret = push_node_left(trans, root,
565 left_buf, mid_buf);
566 }
Chris Mason33ade1f2007-04-20 13:48:57 -0400567 }
Chris Masone66f7092007-04-20 13:16:02 -0400568 if (wret < 0)
569 ret = wret;
570 if (wret == 0) {
571 orig_slot += left_nr;
572 btrfs_memcpy(root, parent,
573 &parent->ptrs[pslot].key,
574 &mid->ptrs[0].key,
575 sizeof(struct btrfs_disk_key));
576 btrfs_mark_buffer_dirty(parent_buf);
577 if (btrfs_header_nritems(&left->header) > orig_slot) {
578 path->nodes[level] = left_buf;
579 path->slots[level + 1] -= 1;
580 path->slots[level] = orig_slot;
581 btrfs_block_release(root, mid_buf);
582 } else {
583 orig_slot -=
584 btrfs_header_nritems(&left->header);
585 path->slots[level] = orig_slot;
586 btrfs_block_release(root, left_buf);
587 }
588 check_node(root, path, level);
589 return 0;
590 }
591 btrfs_block_release(root, left_buf);
592 }
593 right_buf = read_node_slot(root, parent_buf, pslot + 1);
594
595 /*
596 * then try to empty the right most buffer into the middle
597 */
598 if (right_buf) {
Chris Mason33ade1f2007-04-20 13:48:57 -0400599 u32 right_nr;
Chris Masone66f7092007-04-20 13:16:02 -0400600 right = btrfs_buffer_node(right_buf);
Chris Mason33ade1f2007-04-20 13:48:57 -0400601 right_nr = btrfs_header_nritems(&right->header);
602 if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
603 wret = 1;
604 } else {
Chris Mason54aa1f42007-06-22 14:16:25 -0400605 ret = btrfs_cow_block(trans, root, right_buf,
606 parent_buf, pslot + 1,
607 &right_buf);
608 if (ret)
609 wret = 1;
610 else {
611 right = btrfs_buffer_node(right_buf);
612 wret = balance_node_right(trans, root,
613 right_buf, mid_buf);
614 }
Chris Mason33ade1f2007-04-20 13:48:57 -0400615 }
Chris Masone66f7092007-04-20 13:16:02 -0400616 if (wret < 0)
617 ret = wret;
618 if (wret == 0) {
619 btrfs_memcpy(root, parent,
620 &parent->ptrs[pslot + 1].key,
621 &right->ptrs[0].key,
622 sizeof(struct btrfs_disk_key));
623 btrfs_mark_buffer_dirty(parent_buf);
624 if (btrfs_header_nritems(&mid->header) <= orig_slot) {
625 path->nodes[level] = right_buf;
626 path->slots[level + 1] += 1;
627 path->slots[level] = orig_slot -
628 btrfs_header_nritems(&mid->header);
629 btrfs_block_release(root, mid_buf);
630 } else {
631 btrfs_block_release(root, right_buf);
632 }
633 check_node(root, path, level);
634 return 0;
635 }
636 btrfs_block_release(root, right_buf);
637 }
638 check_node(root, path, level);
639 return 1;
640}
641
Chris Mason74123bd2007-02-02 11:05:29 -0500642/*
643 * look for key in the tree. path is filled in with nodes along the way
644 * if key is found, we return zero and you can find the item in the leaf
645 * level of the path (level 0)
646 *
647 * If the key isn't found, the path points to the slot where it should
Chris Masonaa5d6be2007-02-28 16:35:06 -0500648 * be inserted, and 1 is returned. If there are other errors during the
649 * search a negative error number is returned.
Chris Mason97571fd2007-02-24 13:39:08 -0500650 *
651 * if ins_len > 0, nodes and leaves will be split as we walk down the
652 * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if
653 * possible)
Chris Mason74123bd2007-02-02 11:05:29 -0500654 */
Chris Masone089f052007-03-16 16:20:31 -0400655int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
656 *root, struct btrfs_key *key, struct btrfs_path *p, int
657 ins_len, int cow)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500658{
Chris Masone20d96d2007-03-22 12:13:20 -0400659 struct buffer_head *b;
660 struct buffer_head *cow_buf;
Chris Mason234b63a2007-03-13 10:46:10 -0400661 struct btrfs_node *c;
Chris Mason9f3a7422007-08-07 15:52:19 -0400662 struct btrfs_root_item *root_item = &root->root_item;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500663 int slot;
664 int ret;
665 int level;
Chris Mason9f3a7422007-08-07 15:52:19 -0400666 u8 lowest_level = 0;
667
668 if (btrfs_root_refs(root_item) == 0 && root->ref_cows) {
669 lowest_level = root_item->drop_level;
670 WARN_ON(ins_len || cow);
671 }
Chris Mason5c680ed2007-02-22 11:39:13 -0500672
Chris Mason22b0ebd2007-03-30 08:47:31 -0400673 WARN_ON(p->nodes[0] != NULL);
674 WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
Chris Masonbb803952007-03-01 12:04:21 -0500675again:
676 b = root->node;
Chris Masone20d96d2007-03-22 12:13:20 -0400677 get_bh(b);
Chris Masoneb60cea2007-02-02 09:18:22 -0500678 while (b) {
Chris Masone20d96d2007-03-22 12:13:20 -0400679 c = btrfs_buffer_node(b);
680 level = btrfs_header_level(&c->header);
Chris Mason02217ed2007-03-02 16:08:05 -0500681 if (cow) {
682 int wret;
Chris Masone20d96d2007-03-22 12:13:20 -0400683 wret = btrfs_cow_block(trans, root, b,
684 p->nodes[level + 1],
685 p->slots[level + 1],
Chris Masone089f052007-03-16 16:20:31 -0400686 &cow_buf);
Chris Mason54aa1f42007-06-22 14:16:25 -0400687 if (wret) {
688 btrfs_block_release(root, cow_buf);
689 return wret;
690 }
Chris Mason02217ed2007-03-02 16:08:05 -0500691 b = cow_buf;
Chris Mason2c90e5d2007-04-02 10:50:19 -0400692 c = btrfs_buffer_node(b);
Chris Mason02217ed2007-03-02 16:08:05 -0500693 }
694 BUG_ON(!cow && ins_len);
Chris Mason2c90e5d2007-04-02 10:50:19 -0400695 if (level != btrfs_header_level(&c->header))
696 WARN_ON(1);
697 level = btrfs_header_level(&c->header);
Chris Masoneb60cea2007-02-02 09:18:22 -0500698 p->nodes[level] = b;
Chris Mason123abc82007-03-14 14:14:43 -0400699 ret = check_block(root, p, level);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500700 if (ret)
701 return -1;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500702 ret = bin_search(c, key, &slot);
Chris Mason7518a232007-03-12 12:01:18 -0400703 if (!btrfs_is_leaf(c)) {
Chris Masonbe0e5c02007-01-26 15:51:26 -0500704 if (ret && slot > 0)
705 slot -= 1;
706 p->slots[level] = slot;
Chris Masond4dbff92007-04-04 14:08:15 -0400707 if (ins_len > 0 && btrfs_header_nritems(&c->header) >=
708 BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
Chris Masone089f052007-03-16 16:20:31 -0400709 int sret = split_node(trans, root, p, level);
Chris Mason5c680ed2007-02-22 11:39:13 -0500710 BUG_ON(sret > 0);
711 if (sret)
712 return sret;
713 b = p->nodes[level];
Chris Masone20d96d2007-03-22 12:13:20 -0400714 c = btrfs_buffer_node(b);
Chris Mason5c680ed2007-02-22 11:39:13 -0500715 slot = p->slots[level];
Chris Masonbb803952007-03-01 12:04:21 -0500716 } else if (ins_len < 0) {
Chris Masone089f052007-03-16 16:20:31 -0400717 int sret = balance_level(trans, root, p,
718 level);
Chris Masonbb803952007-03-01 12:04:21 -0500719 if (sret)
720 return sret;
721 b = p->nodes[level];
722 if (!b)
723 goto again;
Chris Masone20d96d2007-03-22 12:13:20 -0400724 c = btrfs_buffer_node(b);
Chris Masonbb803952007-03-01 12:04:21 -0500725 slot = p->slots[level];
Chris Mason7518a232007-03-12 12:01:18 -0400726 BUG_ON(btrfs_header_nritems(&c->header) == 1);
Chris Mason5c680ed2007-02-22 11:39:13 -0500727 }
Chris Mason9f3a7422007-08-07 15:52:19 -0400728 /* this is only true while dropping a snapshot */
729 if (level == lowest_level)
730 break;
Chris Mason1d4f8a02007-03-13 09:28:32 -0400731 b = read_tree_block(root, btrfs_node_blockptr(c, slot));
Chris Masonbe0e5c02007-01-26 15:51:26 -0500732 } else {
Chris Mason234b63a2007-03-13 10:46:10 -0400733 struct btrfs_leaf *l = (struct btrfs_leaf *)c;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500734 p->slots[level] = slot;
Chris Mason123abc82007-03-14 14:14:43 -0400735 if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
Chris Mason0783fcf2007-03-12 20:12:07 -0400736 sizeof(struct btrfs_item) + ins_len) {
Chris Masond4dbff92007-04-04 14:08:15 -0400737 int sret = split_leaf(trans, root, key,
738 p, ins_len);
Chris Mason5c680ed2007-02-22 11:39:13 -0500739 BUG_ON(sret > 0);
740 if (sret)
741 return sret;
742 }
Chris Masonbe0e5c02007-01-26 15:51:26 -0500743 return ret;
744 }
745 }
Chris Masonaa5d6be2007-02-28 16:35:06 -0500746 return 1;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500747}
748
Chris Mason74123bd2007-02-02 11:05:29 -0500749/*
750 * adjust the pointers going up the tree, starting at level
751 * making sure the right key of each node is points to 'key'.
752 * This is used after shifting pointers to the left, so it stops
753 * fixing up pointers when a given leaf/node is not in slot 0 of the
754 * higher levels
Chris Masonaa5d6be2007-02-28 16:35:06 -0500755 *
756 * If this fails to write a tree block, it returns -1, but continues
757 * fixing up the blocks in ram so the tree is consistent.
Chris Mason74123bd2007-02-02 11:05:29 -0500758 */
Chris Masone089f052007-03-16 16:20:31 -0400759static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
760 *root, struct btrfs_path *path, struct btrfs_disk_key
761 *key, int level)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500762{
763 int i;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500764 int ret = 0;
Chris Mason234b63a2007-03-13 10:46:10 -0400765 for (i = level; i < BTRFS_MAX_LEVEL; i++) {
766 struct btrfs_node *t;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500767 int tslot = path->slots[i];
Chris Masoneb60cea2007-02-02 09:18:22 -0500768 if (!path->nodes[i])
Chris Masonbe0e5c02007-01-26 15:51:26 -0500769 break;
Chris Masone20d96d2007-03-22 12:13:20 -0400770 t = btrfs_buffer_node(path->nodes[i]);
Chris Masond6025572007-03-30 14:27:56 -0400771 btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key));
772 btrfs_mark_buffer_dirty(path->nodes[i]);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500773 if (tslot != 0)
774 break;
775 }
Chris Masonaa5d6be2007-02-28 16:35:06 -0500776 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500777}
778
Chris Mason74123bd2007-02-02 11:05:29 -0500779/*
780 * try to push data from one node into the next node left in the
Chris Mason79f95c82007-03-01 15:16:26 -0500781 * tree.
Chris Masonaa5d6be2007-02-28 16:35:06 -0500782 *
783 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
784 * error, and > 0 if there was no room in the left hand block.
Chris Mason74123bd2007-02-02 11:05:29 -0500785 */
Chris Masone089f052007-03-16 16:20:31 -0400786static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masone20d96d2007-03-22 12:13:20 -0400787 *root, struct buffer_head *dst_buf, struct
788 buffer_head *src_buf)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500789{
Chris Masone20d96d2007-03-22 12:13:20 -0400790 struct btrfs_node *src = btrfs_buffer_node(src_buf);
791 struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500792 int push_items = 0;
Chris Masonbb803952007-03-01 12:04:21 -0500793 int src_nritems;
794 int dst_nritems;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500795 int ret = 0;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500796
Chris Mason7518a232007-03-12 12:01:18 -0400797 src_nritems = btrfs_header_nritems(&src->header);
798 dst_nritems = btrfs_header_nritems(&dst->header);
Chris Mason123abc82007-03-14 14:14:43 -0400799 push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
Chris Mason54aa1f42007-06-22 14:16:25 -0400800
Chris Masoneb60cea2007-02-02 09:18:22 -0500801 if (push_items <= 0) {
Chris Masonbe0e5c02007-01-26 15:51:26 -0500802 return 1;
Chris Masoneb60cea2007-02-02 09:18:22 -0500803 }
Chris Masonbe0e5c02007-01-26 15:51:26 -0500804
805 if (src_nritems < push_items)
Chris Mason79f95c82007-03-01 15:16:26 -0500806 push_items = src_nritems;
807
Chris Masond6025572007-03-30 14:27:56 -0400808 btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs,
809 push_items * sizeof(struct btrfs_key_ptr));
Chris Masonbb803952007-03-01 12:04:21 -0500810 if (push_items < src_nritems) {
Chris Masond6025572007-03-30 14:27:56 -0400811 btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items,
Chris Masone2fa7222007-03-12 16:22:34 -0400812 (src_nritems - push_items) *
Chris Mason123abc82007-03-14 14:14:43 -0400813 sizeof(struct btrfs_key_ptr));
Chris Masonbb803952007-03-01 12:04:21 -0500814 }
Chris Mason7518a232007-03-12 12:01:18 -0400815 btrfs_set_header_nritems(&src->header, src_nritems - push_items);
816 btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
Chris Masond6025572007-03-30 14:27:56 -0400817 btrfs_mark_buffer_dirty(src_buf);
818 btrfs_mark_buffer_dirty(dst_buf);
Chris Masonbb803952007-03-01 12:04:21 -0500819 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500820}
821
Chris Mason97571fd2007-02-24 13:39:08 -0500822/*
Chris Mason79f95c82007-03-01 15:16:26 -0500823 * try to push data from one node into the next node right in the
824 * tree.
825 *
826 * returns 0 if some ptrs were pushed, < 0 if there was some horrible
827 * error, and > 0 if there was no room in the right hand block.
828 *
829 * this will only push up to 1/2 the contents of the left node over
830 */
Chris Masone089f052007-03-16 16:20:31 -0400831static int balance_node_right(struct btrfs_trans_handle *trans, struct
Chris Masone20d96d2007-03-22 12:13:20 -0400832 btrfs_root *root, struct buffer_head *dst_buf,
833 struct buffer_head *src_buf)
Chris Mason79f95c82007-03-01 15:16:26 -0500834{
Chris Masone20d96d2007-03-22 12:13:20 -0400835 struct btrfs_node *src = btrfs_buffer_node(src_buf);
836 struct btrfs_node *dst = btrfs_buffer_node(dst_buf);
Chris Mason79f95c82007-03-01 15:16:26 -0500837 int push_items = 0;
838 int max_push;
839 int src_nritems;
840 int dst_nritems;
841 int ret = 0;
Chris Mason79f95c82007-03-01 15:16:26 -0500842
Chris Mason7518a232007-03-12 12:01:18 -0400843 src_nritems = btrfs_header_nritems(&src->header);
844 dst_nritems = btrfs_header_nritems(&dst->header);
Chris Mason123abc82007-03-14 14:14:43 -0400845 push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
Chris Mason79f95c82007-03-01 15:16:26 -0500846 if (push_items <= 0) {
847 return 1;
848 }
849
850 max_push = src_nritems / 2 + 1;
851 /* don't try to empty the node */
852 if (max_push > src_nritems)
853 return 1;
854 if (max_push < push_items)
855 push_items = max_push;
856
Chris Masond6025572007-03-30 14:27:56 -0400857 btrfs_memmove(root, dst, dst->ptrs + push_items, dst->ptrs,
858 dst_nritems * sizeof(struct btrfs_key_ptr));
859
860 btrfs_memcpy(root, dst, dst->ptrs,
861 src->ptrs + src_nritems - push_items,
862 push_items * sizeof(struct btrfs_key_ptr));
Chris Mason79f95c82007-03-01 15:16:26 -0500863
Chris Mason7518a232007-03-12 12:01:18 -0400864 btrfs_set_header_nritems(&src->header, src_nritems - push_items);
865 btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
Chris Mason79f95c82007-03-01 15:16:26 -0500866
Chris Masond6025572007-03-30 14:27:56 -0400867 btrfs_mark_buffer_dirty(src_buf);
868 btrfs_mark_buffer_dirty(dst_buf);
Chris Mason79f95c82007-03-01 15:16:26 -0500869 return ret;
870}
871
872/*
Chris Mason97571fd2007-02-24 13:39:08 -0500873 * helper function to insert a new root level in the tree.
874 * A new node is allocated, and a single item is inserted to
875 * point to the existing root
Chris Masonaa5d6be2007-02-28 16:35:06 -0500876 *
877 * returns zero on success or < 0 on failure.
Chris Mason97571fd2007-02-24 13:39:08 -0500878 */
Chris Masone089f052007-03-16 16:20:31 -0400879static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
880 *root, struct btrfs_path *path, int level)
Chris Mason5c680ed2007-02-22 11:39:13 -0500881{
Chris Masone20d96d2007-03-22 12:13:20 -0400882 struct buffer_head *t;
Chris Mason234b63a2007-03-13 10:46:10 -0400883 struct btrfs_node *lower;
884 struct btrfs_node *c;
Chris Masone2fa7222007-03-12 16:22:34 -0400885 struct btrfs_disk_key *lower_key;
Chris Mason5c680ed2007-02-22 11:39:13 -0500886
887 BUG_ON(path->nodes[level]);
888 BUG_ON(path->nodes[level-1] != root->node);
889
Chris Mason31f3c992007-04-30 15:25:45 -0400890 t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr);
Chris Mason54aa1f42007-06-22 14:16:25 -0400891 if (IS_ERR(t))
892 return PTR_ERR(t);
Chris Masone20d96d2007-03-22 12:13:20 -0400893 c = btrfs_buffer_node(t);
Chris Mason123abc82007-03-14 14:14:43 -0400894 memset(c, 0, root->blocksize);
Chris Mason7518a232007-03-12 12:01:18 -0400895 btrfs_set_header_nritems(&c->header, 1);
896 btrfs_set_header_level(&c->header, level);
Chris Mason7eccb902007-04-11 15:53:25 -0400897 btrfs_set_header_blocknr(&c->header, bh_blocknr(t));
Chris Mason7f5c1512007-03-23 15:56:19 -0400898 btrfs_set_header_generation(&c->header, trans->transid);
Chris Mason4d775672007-04-20 20:23:12 -0400899 btrfs_set_header_owner(&c->header, root->root_key.objectid);
Chris Masone20d96d2007-03-22 12:13:20 -0400900 lower = btrfs_buffer_node(path->nodes[level-1]);
Chris Mason3eb03142007-04-05 14:28:50 -0400901 memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
902 sizeof(c->header.fsid));
Chris Mason7518a232007-03-12 12:01:18 -0400903 if (btrfs_is_leaf(lower))
Chris Mason234b63a2007-03-13 10:46:10 -0400904 lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
Chris Mason5c680ed2007-02-22 11:39:13 -0500905 else
Chris Mason123abc82007-03-14 14:14:43 -0400906 lower_key = &lower->ptrs[0].key;
Chris Masond6025572007-03-30 14:27:56 -0400907 btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key,
908 sizeof(struct btrfs_disk_key));
Chris Mason7eccb902007-04-11 15:53:25 -0400909 btrfs_set_node_blockptr(c, 0, bh_blocknr(path->nodes[level - 1]));
Chris Masond5719762007-03-23 10:01:08 -0400910
Chris Masond6025572007-03-30 14:27:56 -0400911 btrfs_mark_buffer_dirty(t);
Chris Masond5719762007-03-23 10:01:08 -0400912
Chris Mason5c680ed2007-02-22 11:39:13 -0500913 /* the super has an extra ref to root->node */
Chris Mason234b63a2007-03-13 10:46:10 -0400914 btrfs_block_release(root, root->node);
Chris Mason5c680ed2007-02-22 11:39:13 -0500915 root->node = t;
Chris Masone20d96d2007-03-22 12:13:20 -0400916 get_bh(t);
Chris Mason5c680ed2007-02-22 11:39:13 -0500917 path->nodes[level] = t;
918 path->slots[level] = 0;
919 return 0;
920}
921
Chris Mason74123bd2007-02-02 11:05:29 -0500922/*
923 * worker function to insert a single pointer in a node.
924 * the node should have enough room for the pointer already
Chris Mason97571fd2007-02-24 13:39:08 -0500925 *
Chris Mason74123bd2007-02-02 11:05:29 -0500926 * slot and level indicate where you want the key to go, and
927 * blocknr is the block the key points to.
Chris Masonaa5d6be2007-02-28 16:35:06 -0500928 *
929 * returns zero on success and < 0 on any error
Chris Mason74123bd2007-02-02 11:05:29 -0500930 */
Chris Masone089f052007-03-16 16:20:31 -0400931static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
932 *root, struct btrfs_path *path, struct btrfs_disk_key
933 *key, u64 blocknr, int slot, int level)
Chris Mason74123bd2007-02-02 11:05:29 -0500934{
Chris Mason234b63a2007-03-13 10:46:10 -0400935 struct btrfs_node *lower;
Chris Mason74123bd2007-02-02 11:05:29 -0500936 int nritems;
Chris Mason5c680ed2007-02-22 11:39:13 -0500937
938 BUG_ON(!path->nodes[level]);
Chris Masone20d96d2007-03-22 12:13:20 -0400939 lower = btrfs_buffer_node(path->nodes[level]);
Chris Mason7518a232007-03-12 12:01:18 -0400940 nritems = btrfs_header_nritems(&lower->header);
Chris Mason74123bd2007-02-02 11:05:29 -0500941 if (slot > nritems)
942 BUG();
Chris Mason123abc82007-03-14 14:14:43 -0400943 if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
Chris Mason74123bd2007-02-02 11:05:29 -0500944 BUG();
945 if (slot != nritems) {
Chris Masond6025572007-03-30 14:27:56 -0400946 btrfs_memmove(root, lower, lower->ptrs + slot + 1,
947 lower->ptrs + slot,
948 (nritems - slot) * sizeof(struct btrfs_key_ptr));
Chris Mason74123bd2007-02-02 11:05:29 -0500949 }
Chris Masond6025572007-03-30 14:27:56 -0400950 btrfs_memcpy(root, lower, &lower->ptrs[slot].key,
951 key, sizeof(struct btrfs_disk_key));
Chris Mason1d4f8a02007-03-13 09:28:32 -0400952 btrfs_set_node_blockptr(lower, slot, blocknr);
Chris Mason7518a232007-03-12 12:01:18 -0400953 btrfs_set_header_nritems(&lower->header, nritems + 1);
Chris Masond6025572007-03-30 14:27:56 -0400954 btrfs_mark_buffer_dirty(path->nodes[level]);
Chris Mason098f59c2007-05-11 11:33:21 -0400955 check_node(root, path, level);
Chris Mason74123bd2007-02-02 11:05:29 -0500956 return 0;
957}
958
Chris Mason97571fd2007-02-24 13:39:08 -0500959/*
960 * split the node at the specified level in path in two.
961 * The path is corrected to point to the appropriate node after the split
962 *
963 * Before splitting this tries to make some room in the node by pushing
964 * left and right, if either one works, it returns right away.
Chris Masonaa5d6be2007-02-28 16:35:06 -0500965 *
966 * returns 0 on success and < 0 on failure
Chris Mason97571fd2007-02-24 13:39:08 -0500967 */
Chris Masone089f052007-03-16 16:20:31 -0400968static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
969 *root, struct btrfs_path *path, int level)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500970{
Chris Masone20d96d2007-03-22 12:13:20 -0400971 struct buffer_head *t;
Chris Mason234b63a2007-03-13 10:46:10 -0400972 struct btrfs_node *c;
Chris Masone20d96d2007-03-22 12:13:20 -0400973 struct buffer_head *split_buffer;
Chris Mason234b63a2007-03-13 10:46:10 -0400974 struct btrfs_node *split;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500975 int mid;
Chris Mason5c680ed2007-02-22 11:39:13 -0500976 int ret;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500977 int wret;
Chris Mason7518a232007-03-12 12:01:18 -0400978 u32 c_nritems;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500979
Chris Mason5c680ed2007-02-22 11:39:13 -0500980 t = path->nodes[level];
Chris Masone20d96d2007-03-22 12:13:20 -0400981 c = btrfs_buffer_node(t);
Chris Mason5c680ed2007-02-22 11:39:13 -0500982 if (t == root->node) {
983 /* trying to split the root, lets make a new one */
Chris Masone089f052007-03-16 16:20:31 -0400984 ret = insert_new_root(trans, root, path, level + 1);
Chris Mason5c680ed2007-02-22 11:39:13 -0500985 if (ret)
986 return ret;
Chris Masone66f7092007-04-20 13:16:02 -0400987 } else {
988 ret = push_nodes_for_insert(trans, root, path, level);
989 t = path->nodes[level];
990 c = btrfs_buffer_node(t);
991 if (!ret &&
992 btrfs_header_nritems(&c->header) <
993 BTRFS_NODEPTRS_PER_BLOCK(root) - 1)
994 return 0;
Chris Mason54aa1f42007-06-22 14:16:25 -0400995 if (ret < 0)
996 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500997 }
Chris Masone66f7092007-04-20 13:16:02 -0400998
Chris Mason7518a232007-03-12 12:01:18 -0400999 c_nritems = btrfs_header_nritems(&c->header);
Chris Mason31f3c992007-04-30 15:25:45 -04001000 split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr);
Chris Mason54aa1f42007-06-22 14:16:25 -04001001 if (IS_ERR(split_buffer))
1002 return PTR_ERR(split_buffer);
1003
Chris Masone20d96d2007-03-22 12:13:20 -04001004 split = btrfs_buffer_node(split_buffer);
Chris Mason7518a232007-03-12 12:01:18 -04001005 btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
Chris Mason9a6f11e2007-03-27 09:06:38 -04001006 btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
Chris Mason7eccb902007-04-11 15:53:25 -04001007 btrfs_set_header_blocknr(&split->header, bh_blocknr(split_buffer));
Chris Mason7f5c1512007-03-23 15:56:19 -04001008 btrfs_set_header_generation(&split->header, trans->transid);
Chris Mason4d775672007-04-20 20:23:12 -04001009 btrfs_set_header_owner(&split->header, root->root_key.objectid);
Chris Mason3eb03142007-04-05 14:28:50 -04001010 memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
1011 sizeof(split->header.fsid));
Chris Mason7518a232007-03-12 12:01:18 -04001012 mid = (c_nritems + 1) / 2;
Chris Masond6025572007-03-30 14:27:56 -04001013 btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid,
1014 (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
Chris Mason7518a232007-03-12 12:01:18 -04001015 btrfs_set_header_nritems(&split->header, c_nritems - mid);
1016 btrfs_set_header_nritems(&c->header, mid);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001017 ret = 0;
1018
Chris Masond6025572007-03-30 14:27:56 -04001019 btrfs_mark_buffer_dirty(t);
1020 btrfs_mark_buffer_dirty(split_buffer);
Chris Masone089f052007-03-16 16:20:31 -04001021 wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
Chris Mason7eccb902007-04-11 15:53:25 -04001022 bh_blocknr(split_buffer), path->slots[level + 1] + 1,
Chris Mason123abc82007-03-14 14:14:43 -04001023 level + 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001024 if (wret)
1025 ret = wret;
1026
Chris Mason5de08d72007-02-24 06:24:44 -05001027 if (path->slots[level] >= mid) {
Chris Mason5c680ed2007-02-22 11:39:13 -05001028 path->slots[level] -= mid;
Chris Mason234b63a2007-03-13 10:46:10 -04001029 btrfs_block_release(root, t);
Chris Mason5c680ed2007-02-22 11:39:13 -05001030 path->nodes[level] = split_buffer;
1031 path->slots[level + 1] += 1;
1032 } else {
Chris Mason234b63a2007-03-13 10:46:10 -04001033 btrfs_block_release(root, split_buffer);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001034 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001035 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001036}
1037
Chris Mason74123bd2007-02-02 11:05:29 -05001038/*
1039 * how many bytes are required to store the items in a leaf. start
1040 * and nr indicate which items in the leaf to check. This totals up the
1041 * space used both by the item structs and the item data
1042 */
Chris Mason234b63a2007-03-13 10:46:10 -04001043static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001044{
1045 int data_len;
Chris Masond4dbff92007-04-04 14:08:15 -04001046 int nritems = btrfs_header_nritems(&l->header);
1047 int end = min(nritems, start + nr) - 1;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001048
1049 if (!nr)
1050 return 0;
Chris Mason0783fcf2007-03-12 20:12:07 -04001051 data_len = btrfs_item_end(l->items + start);
1052 data_len = data_len - btrfs_item_offset(l->items + end);
1053 data_len += sizeof(struct btrfs_item) * nr;
Chris Masond4dbff92007-04-04 14:08:15 -04001054 WARN_ON(data_len < 0);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001055 return data_len;
1056}
1057
Chris Mason74123bd2007-02-02 11:05:29 -05001058/*
Chris Masond4dbff92007-04-04 14:08:15 -04001059 * The space between the end of the leaf items and
1060 * the start of the leaf data. IOW, how much room
1061 * the leaf has left for both items and data
1062 */
1063int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf)
1064{
1065 int nritems = btrfs_header_nritems(&leaf->header);
1066 return BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
1067}
1068
1069/*
Chris Mason00ec4c52007-02-24 12:47:20 -05001070 * push some data in the path leaf to the right, trying to free up at
1071 * least data_size bytes. returns zero if the push worked, nonzero otherwise
Chris Masonaa5d6be2007-02-28 16:35:06 -05001072 *
1073 * returns 1 if the push failed because the other node didn't have enough
1074 * room, 0 if everything worked out and < 0 if there were major errors.
Chris Mason00ec4c52007-02-24 12:47:20 -05001075 */
Chris Masone089f052007-03-16 16:20:31 -04001076static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1077 *root, struct btrfs_path *path, int data_size)
Chris Mason00ec4c52007-02-24 12:47:20 -05001078{
Chris Masone20d96d2007-03-22 12:13:20 -04001079 struct buffer_head *left_buf = path->nodes[0];
1080 struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf);
Chris Mason234b63a2007-03-13 10:46:10 -04001081 struct btrfs_leaf *right;
Chris Masone20d96d2007-03-22 12:13:20 -04001082 struct buffer_head *right_buf;
1083 struct buffer_head *upper;
1084 struct btrfs_node *upper_node;
Chris Mason00ec4c52007-02-24 12:47:20 -05001085 int slot;
1086 int i;
1087 int free_space;
1088 int push_space = 0;
1089 int push_items = 0;
Chris Mason0783fcf2007-03-12 20:12:07 -04001090 struct btrfs_item *item;
Chris Mason7518a232007-03-12 12:01:18 -04001091 u32 left_nritems;
1092 u32 right_nritems;
Chris Mason54aa1f42007-06-22 14:16:25 -04001093 int ret;
Chris Mason00ec4c52007-02-24 12:47:20 -05001094
1095 slot = path->slots[1];
1096 if (!path->nodes[1]) {
1097 return 1;
1098 }
1099 upper = path->nodes[1];
Chris Masone20d96d2007-03-22 12:13:20 -04001100 upper_node = btrfs_buffer_node(upper);
1101 if (slot >= btrfs_header_nritems(&upper_node->header) - 1) {
Chris Mason00ec4c52007-02-24 12:47:20 -05001102 return 1;
1103 }
Chris Masone20d96d2007-03-22 12:13:20 -04001104 right_buf = read_tree_block(root,
1105 btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1));
1106 right = btrfs_buffer_leaf(right_buf);
Chris Mason123abc82007-03-14 14:14:43 -04001107 free_space = btrfs_leaf_free_space(root, right);
Chris Mason0783fcf2007-03-12 20:12:07 -04001108 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason234b63a2007-03-13 10:46:10 -04001109 btrfs_block_release(root, right_buf);
Chris Mason00ec4c52007-02-24 12:47:20 -05001110 return 1;
1111 }
Chris Mason02217ed2007-03-02 16:08:05 -05001112 /* cow and double check */
Chris Mason54aa1f42007-06-22 14:16:25 -04001113 ret = btrfs_cow_block(trans, root, right_buf, upper,
1114 slot + 1, &right_buf);
1115 if (ret) {
1116 btrfs_block_release(root, right_buf);
1117 return 1;
1118 }
Chris Masone20d96d2007-03-22 12:13:20 -04001119 right = btrfs_buffer_leaf(right_buf);
Chris Mason123abc82007-03-14 14:14:43 -04001120 free_space = btrfs_leaf_free_space(root, right);
Chris Mason0783fcf2007-03-12 20:12:07 -04001121 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason234b63a2007-03-13 10:46:10 -04001122 btrfs_block_release(root, right_buf);
Chris Mason02217ed2007-03-02 16:08:05 -05001123 return 1;
1124 }
1125
Chris Mason7518a232007-03-12 12:01:18 -04001126 left_nritems = btrfs_header_nritems(&left->header);
Chris Masona429e512007-04-18 16:15:28 -04001127 if (left_nritems == 0) {
1128 btrfs_block_release(root, right_buf);
1129 return 1;
1130 }
1131 for (i = left_nritems - 1; i >= 1; i--) {
Chris Mason00ec4c52007-02-24 12:47:20 -05001132 item = left->items + i;
1133 if (path->slots[0] == i)
1134 push_space += data_size + sizeof(*item);
Chris Mason0783fcf2007-03-12 20:12:07 -04001135 if (btrfs_item_size(item) + sizeof(*item) + push_space >
1136 free_space)
Chris Mason00ec4c52007-02-24 12:47:20 -05001137 break;
1138 push_items++;
Chris Mason0783fcf2007-03-12 20:12:07 -04001139 push_space += btrfs_item_size(item) + sizeof(*item);
Chris Mason00ec4c52007-02-24 12:47:20 -05001140 }
1141 if (push_items == 0) {
Chris Mason234b63a2007-03-13 10:46:10 -04001142 btrfs_block_release(root, right_buf);
Chris Mason00ec4c52007-02-24 12:47:20 -05001143 return 1;
1144 }
Chris Masona429e512007-04-18 16:15:28 -04001145 if (push_items == left_nritems)
1146 WARN_ON(1);
Chris Mason7518a232007-03-12 12:01:18 -04001147 right_nritems = btrfs_header_nritems(&right->header);
Chris Mason00ec4c52007-02-24 12:47:20 -05001148 /* push left to right */
Chris Mason0783fcf2007-03-12 20:12:07 -04001149 push_space = btrfs_item_end(left->items + left_nritems - push_items);
Chris Mason123abc82007-03-14 14:14:43 -04001150 push_space -= leaf_data_end(root, left);
Chris Mason00ec4c52007-02-24 12:47:20 -05001151 /* make room in the right data area */
Chris Masond6025572007-03-30 14:27:56 -04001152 btrfs_memmove(root, right, btrfs_leaf_data(right) +
1153 leaf_data_end(root, right) - push_space,
1154 btrfs_leaf_data(right) +
1155 leaf_data_end(root, right), BTRFS_LEAF_DATA_SIZE(root) -
1156 leaf_data_end(root, right));
Chris Mason00ec4c52007-02-24 12:47:20 -05001157 /* copy from the left data area */
Chris Masond6025572007-03-30 14:27:56 -04001158 btrfs_memcpy(root, right, btrfs_leaf_data(right) +
1159 BTRFS_LEAF_DATA_SIZE(root) - push_space,
1160 btrfs_leaf_data(left) + leaf_data_end(root, left),
1161 push_space);
1162 btrfs_memmove(root, right, right->items + push_items, right->items,
Chris Mason0783fcf2007-03-12 20:12:07 -04001163 right_nritems * sizeof(struct btrfs_item));
Chris Mason00ec4c52007-02-24 12:47:20 -05001164 /* copy the items from left to right */
Chris Masond6025572007-03-30 14:27:56 -04001165 btrfs_memcpy(root, right, right->items, left->items +
1166 left_nritems - push_items,
1167 push_items * sizeof(struct btrfs_item));
Chris Mason00ec4c52007-02-24 12:47:20 -05001168
1169 /* update the item pointers */
Chris Mason7518a232007-03-12 12:01:18 -04001170 right_nritems += push_items;
1171 btrfs_set_header_nritems(&right->header, right_nritems);
Chris Mason123abc82007-03-14 14:14:43 -04001172 push_space = BTRFS_LEAF_DATA_SIZE(root);
Chris Mason7518a232007-03-12 12:01:18 -04001173 for (i = 0; i < right_nritems; i++) {
Chris Mason0783fcf2007-03-12 20:12:07 -04001174 btrfs_set_item_offset(right->items + i, push_space -
1175 btrfs_item_size(right->items + i));
1176 push_space = btrfs_item_offset(right->items + i);
Chris Mason00ec4c52007-02-24 12:47:20 -05001177 }
Chris Mason7518a232007-03-12 12:01:18 -04001178 left_nritems -= push_items;
1179 btrfs_set_header_nritems(&left->header, left_nritems);
Chris Mason00ec4c52007-02-24 12:47:20 -05001180
Chris Masond6025572007-03-30 14:27:56 -04001181 btrfs_mark_buffer_dirty(left_buf);
1182 btrfs_mark_buffer_dirty(right_buf);
Chris Masona429e512007-04-18 16:15:28 -04001183
Chris Masond6025572007-03-30 14:27:56 -04001184 btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key,
Chris Masone2fa7222007-03-12 16:22:34 -04001185 &right->items[0].key, sizeof(struct btrfs_disk_key));
Chris Masond6025572007-03-30 14:27:56 -04001186 btrfs_mark_buffer_dirty(upper);
Chris Mason02217ed2007-03-02 16:08:05 -05001187
Chris Mason00ec4c52007-02-24 12:47:20 -05001188 /* then fixup the leaf pointer in the path */
Chris Mason7518a232007-03-12 12:01:18 -04001189 if (path->slots[0] >= left_nritems) {
1190 path->slots[0] -= left_nritems;
Chris Mason234b63a2007-03-13 10:46:10 -04001191 btrfs_block_release(root, path->nodes[0]);
Chris Mason00ec4c52007-02-24 12:47:20 -05001192 path->nodes[0] = right_buf;
1193 path->slots[1] += 1;
1194 } else {
Chris Mason234b63a2007-03-13 10:46:10 -04001195 btrfs_block_release(root, right_buf);
Chris Mason00ec4c52007-02-24 12:47:20 -05001196 }
Chris Mason098f59c2007-05-11 11:33:21 -04001197 if (path->nodes[1])
1198 check_node(root, path, 1);
Chris Mason00ec4c52007-02-24 12:47:20 -05001199 return 0;
1200}
1201/*
Chris Mason74123bd2007-02-02 11:05:29 -05001202 * push some data in the path leaf to the left, trying to free up at
1203 * least data_size bytes. returns zero if the push worked, nonzero otherwise
1204 */
Chris Masone089f052007-03-16 16:20:31 -04001205static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1206 *root, struct btrfs_path *path, int data_size)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001207{
Chris Masone20d96d2007-03-22 12:13:20 -04001208 struct buffer_head *right_buf = path->nodes[0];
1209 struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf);
1210 struct buffer_head *t;
Chris Mason234b63a2007-03-13 10:46:10 -04001211 struct btrfs_leaf *left;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001212 int slot;
1213 int i;
1214 int free_space;
1215 int push_space = 0;
1216 int push_items = 0;
Chris Mason0783fcf2007-03-12 20:12:07 -04001217 struct btrfs_item *item;
Chris Mason7518a232007-03-12 12:01:18 -04001218 u32 old_left_nritems;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001219 int ret = 0;
1220 int wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001221
1222 slot = path->slots[1];
1223 if (slot == 0) {
1224 return 1;
1225 }
1226 if (!path->nodes[1]) {
1227 return 1;
1228 }
Chris Masone20d96d2007-03-22 12:13:20 -04001229 t = read_tree_block(root,
1230 btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1));
1231 left = btrfs_buffer_leaf(t);
Chris Mason123abc82007-03-14 14:14:43 -04001232 free_space = btrfs_leaf_free_space(root, left);
Chris Mason0783fcf2007-03-12 20:12:07 -04001233 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason234b63a2007-03-13 10:46:10 -04001234 btrfs_block_release(root, t);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001235 return 1;
1236 }
Chris Mason02217ed2007-03-02 16:08:05 -05001237
1238 /* cow and double check */
Chris Mason54aa1f42007-06-22 14:16:25 -04001239 ret = btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
1240 if (ret) {
1241 /* we hit -ENOSPC, but it isn't fatal here */
1242 return 1;
1243 }
Chris Masone20d96d2007-03-22 12:13:20 -04001244 left = btrfs_buffer_leaf(t);
Chris Mason123abc82007-03-14 14:14:43 -04001245 free_space = btrfs_leaf_free_space(root, left);
Chris Mason0783fcf2007-03-12 20:12:07 -04001246 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason234b63a2007-03-13 10:46:10 -04001247 btrfs_block_release(root, t);
Chris Mason02217ed2007-03-02 16:08:05 -05001248 return 1;
1249 }
1250
Chris Masona429e512007-04-18 16:15:28 -04001251 if (btrfs_header_nritems(&right->header) == 0) {
1252 btrfs_block_release(root, t);
1253 return 1;
1254 }
1255
1256 for (i = 0; i < btrfs_header_nritems(&right->header) - 1; i++) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001257 item = right->items + i;
1258 if (path->slots[0] == i)
1259 push_space += data_size + sizeof(*item);
Chris Mason0783fcf2007-03-12 20:12:07 -04001260 if (btrfs_item_size(item) + sizeof(*item) + push_space >
1261 free_space)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001262 break;
1263 push_items++;
Chris Mason0783fcf2007-03-12 20:12:07 -04001264 push_space += btrfs_item_size(item) + sizeof(*item);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001265 }
1266 if (push_items == 0) {
Chris Mason234b63a2007-03-13 10:46:10 -04001267 btrfs_block_release(root, t);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001268 return 1;
1269 }
Chris Masona429e512007-04-18 16:15:28 -04001270 if (push_items == btrfs_header_nritems(&right->header))
1271 WARN_ON(1);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001272 /* push data from right to left */
Chris Masond6025572007-03-30 14:27:56 -04001273 btrfs_memcpy(root, left, left->items +
1274 btrfs_header_nritems(&left->header),
1275 right->items, push_items * sizeof(struct btrfs_item));
Chris Mason123abc82007-03-14 14:14:43 -04001276 push_space = BTRFS_LEAF_DATA_SIZE(root) -
Chris Mason0783fcf2007-03-12 20:12:07 -04001277 btrfs_item_offset(right->items + push_items -1);
Chris Masond6025572007-03-30 14:27:56 -04001278 btrfs_memcpy(root, left, btrfs_leaf_data(left) +
1279 leaf_data_end(root, left) - push_space,
1280 btrfs_leaf_data(right) +
1281 btrfs_item_offset(right->items + push_items - 1),
1282 push_space);
Chris Mason7518a232007-03-12 12:01:18 -04001283 old_left_nritems = btrfs_header_nritems(&left->header);
Chris Masoneb60cea2007-02-02 09:18:22 -05001284 BUG_ON(old_left_nritems < 0);
1285
Chris Mason0783fcf2007-03-12 20:12:07 -04001286 for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
Chris Mason123abc82007-03-14 14:14:43 -04001287 u32 ioff = btrfs_item_offset(left->items + i);
1288 btrfs_set_item_offset(left->items + i, ioff -
1289 (BTRFS_LEAF_DATA_SIZE(root) -
Chris Mason0783fcf2007-03-12 20:12:07 -04001290 btrfs_item_offset(left->items +
1291 old_left_nritems - 1)));
Chris Masonbe0e5c02007-01-26 15:51:26 -05001292 }
Chris Mason7518a232007-03-12 12:01:18 -04001293 btrfs_set_header_nritems(&left->header, old_left_nritems + push_items);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001294
1295 /* fixup right node */
Chris Mason0783fcf2007-03-12 20:12:07 -04001296 push_space = btrfs_item_offset(right->items + push_items - 1) -
Chris Mason123abc82007-03-14 14:14:43 -04001297 leaf_data_end(root, right);
Chris Masond6025572007-03-30 14:27:56 -04001298 btrfs_memmove(root, right, btrfs_leaf_data(right) +
1299 BTRFS_LEAF_DATA_SIZE(root) - push_space,
1300 btrfs_leaf_data(right) +
1301 leaf_data_end(root, right), push_space);
1302 btrfs_memmove(root, right, right->items, right->items + push_items,
Chris Mason7518a232007-03-12 12:01:18 -04001303 (btrfs_header_nritems(&right->header) - push_items) *
Chris Mason0783fcf2007-03-12 20:12:07 -04001304 sizeof(struct btrfs_item));
Chris Mason7518a232007-03-12 12:01:18 -04001305 btrfs_set_header_nritems(&right->header,
1306 btrfs_header_nritems(&right->header) -
1307 push_items);
Chris Mason123abc82007-03-14 14:14:43 -04001308 push_space = BTRFS_LEAF_DATA_SIZE(root);
Chris Masoneb60cea2007-02-02 09:18:22 -05001309
Chris Mason7518a232007-03-12 12:01:18 -04001310 for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
Chris Mason0783fcf2007-03-12 20:12:07 -04001311 btrfs_set_item_offset(right->items + i, push_space -
1312 btrfs_item_size(right->items + i));
1313 push_space = btrfs_item_offset(right->items + i);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001314 }
Chris Masoneb60cea2007-02-02 09:18:22 -05001315
Chris Masond6025572007-03-30 14:27:56 -04001316 btrfs_mark_buffer_dirty(t);
1317 btrfs_mark_buffer_dirty(right_buf);
Chris Mason098f59c2007-05-11 11:33:21 -04001318
Chris Masone089f052007-03-16 16:20:31 -04001319 wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001320 if (wret)
1321 ret = wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001322
1323 /* then fixup the leaf pointer in the path */
1324 if (path->slots[0] < push_items) {
1325 path->slots[0] += old_left_nritems;
Chris Mason234b63a2007-03-13 10:46:10 -04001326 btrfs_block_release(root, path->nodes[0]);
Chris Masoneb60cea2007-02-02 09:18:22 -05001327 path->nodes[0] = t;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001328 path->slots[1] -= 1;
1329 } else {
Chris Mason234b63a2007-03-13 10:46:10 -04001330 btrfs_block_release(root, t);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001331 path->slots[0] -= push_items;
1332 }
Chris Masoneb60cea2007-02-02 09:18:22 -05001333 BUG_ON(path->slots[0] < 0);
Chris Mason098f59c2007-05-11 11:33:21 -04001334 if (path->nodes[1])
1335 check_node(root, path, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001336 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001337}
1338
Chris Mason74123bd2007-02-02 11:05:29 -05001339/*
1340 * split the path's leaf in two, making sure there is at least data_size
1341 * available for the resulting leaf level of the path.
Chris Masonaa5d6be2007-02-28 16:35:06 -05001342 *
1343 * returns 0 if all went well and < 0 on failure.
Chris Mason74123bd2007-02-02 11:05:29 -05001344 */
Chris Masone089f052007-03-16 16:20:31 -04001345static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masond4dbff92007-04-04 14:08:15 -04001346 *root, struct btrfs_key *ins_key,
1347 struct btrfs_path *path, int data_size)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001348{
Chris Masone20d96d2007-03-22 12:13:20 -04001349 struct buffer_head *l_buf;
Chris Mason234b63a2007-03-13 10:46:10 -04001350 struct btrfs_leaf *l;
Chris Mason7518a232007-03-12 12:01:18 -04001351 u32 nritems;
Chris Masoneb60cea2007-02-02 09:18:22 -05001352 int mid;
1353 int slot;
Chris Mason234b63a2007-03-13 10:46:10 -04001354 struct btrfs_leaf *right;
Chris Masone20d96d2007-03-22 12:13:20 -04001355 struct buffer_head *right_buffer;
Chris Mason0783fcf2007-03-12 20:12:07 -04001356 int space_needed = data_size + sizeof(struct btrfs_item);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001357 int data_copy_size;
1358 int rt_data_off;
1359 int i;
Chris Masond4dbff92007-04-04 14:08:15 -04001360 int ret = 0;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001361 int wret;
Chris Masond4dbff92007-04-04 14:08:15 -04001362 int double_split = 0;
1363 struct btrfs_disk_key disk_key;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001364
Chris Mason40689472007-03-17 14:29:23 -04001365 /* first try to make some room by pushing left and right */
Chris Masone089f052007-03-16 16:20:31 -04001366 wret = push_leaf_left(trans, root, path, data_size);
Chris Masoneaee50e2007-03-13 11:17:52 -04001367 if (wret < 0)
1368 return wret;
1369 if (wret) {
Chris Masone089f052007-03-16 16:20:31 -04001370 wret = push_leaf_right(trans, root, path, data_size);
Chris Masoneaee50e2007-03-13 11:17:52 -04001371 if (wret < 0)
1372 return wret;
1373 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001374 l_buf = path->nodes[0];
Chris Masone20d96d2007-03-22 12:13:20 -04001375 l = btrfs_buffer_leaf(l_buf);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001376
1377 /* did the pushes work? */
Chris Mason123abc82007-03-14 14:14:43 -04001378 if (btrfs_leaf_free_space(root, l) >=
1379 sizeof(struct btrfs_item) + data_size)
Chris Masonaa5d6be2007-02-28 16:35:06 -05001380 return 0;
1381
Chris Mason5c680ed2007-02-22 11:39:13 -05001382 if (!path->nodes[1]) {
Chris Masone089f052007-03-16 16:20:31 -04001383 ret = insert_new_root(trans, root, path, 1);
Chris Mason5c680ed2007-02-22 11:39:13 -05001384 if (ret)
1385 return ret;
1386 }
Chris Masoneb60cea2007-02-02 09:18:22 -05001387 slot = path->slots[0];
Chris Mason7518a232007-03-12 12:01:18 -04001388 nritems = btrfs_header_nritems(&l->header);
Chris Masoneb60cea2007-02-02 09:18:22 -05001389 mid = (nritems + 1)/ 2;
Chris Mason54aa1f42007-06-22 14:16:25 -04001390
Chris Mason31f3c992007-04-30 15:25:45 -04001391 right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
Chris Mason54aa1f42007-06-22 14:16:25 -04001392 if (IS_ERR(right_buffer))
1393 return PTR_ERR(right_buffer);
1394
Chris Masone20d96d2007-03-22 12:13:20 -04001395 right = btrfs_buffer_leaf(right_buffer);
Chris Mason123abc82007-03-14 14:14:43 -04001396 memset(&right->header, 0, sizeof(right->header));
Chris Mason7eccb902007-04-11 15:53:25 -04001397 btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
Chris Mason7f5c1512007-03-23 15:56:19 -04001398 btrfs_set_header_generation(&right->header, trans->transid);
Chris Mason4d775672007-04-20 20:23:12 -04001399 btrfs_set_header_owner(&right->header, root->root_key.objectid);
Chris Mason7518a232007-03-12 12:01:18 -04001400 btrfs_set_header_level(&right->header, 0);
Chris Mason3eb03142007-04-05 14:28:50 -04001401 memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
1402 sizeof(right->header.fsid));
Chris Masond4dbff92007-04-04 14:08:15 -04001403 if (mid <= slot) {
1404 if (nritems == 1 ||
1405 leaf_space_used(l, mid, nritems - mid) + space_needed >
1406 BTRFS_LEAF_DATA_SIZE(root)) {
1407 if (slot >= nritems) {
1408 btrfs_cpu_key_to_disk(&disk_key, ins_key);
1409 btrfs_set_header_nritems(&right->header, 0);
1410 wret = insert_ptr(trans, root, path,
1411 &disk_key,
Chris Mason7eccb902007-04-11 15:53:25 -04001412 bh_blocknr(right_buffer),
Chris Masond4dbff92007-04-04 14:08:15 -04001413 path->slots[1] + 1, 1);
1414 if (wret)
1415 ret = wret;
1416 btrfs_block_release(root, path->nodes[0]);
1417 path->nodes[0] = right_buffer;
1418 path->slots[0] = 0;
1419 path->slots[1] += 1;
1420 return ret;
1421 }
1422 mid = slot;
1423 double_split = 1;
1424 }
1425 } else {
1426 if (leaf_space_used(l, 0, mid + 1) + space_needed >
1427 BTRFS_LEAF_DATA_SIZE(root)) {
1428 if (slot == 0) {
1429 btrfs_cpu_key_to_disk(&disk_key, ins_key);
1430 btrfs_set_header_nritems(&right->header, 0);
1431 wret = insert_ptr(trans, root, path,
1432 &disk_key,
Chris Mason7eccb902007-04-11 15:53:25 -04001433 bh_blocknr(right_buffer),
Chris Mason098f59c2007-05-11 11:33:21 -04001434 path->slots[1], 1);
Chris Masond4dbff92007-04-04 14:08:15 -04001435 if (wret)
1436 ret = wret;
1437 btrfs_block_release(root, path->nodes[0]);
1438 path->nodes[0] = right_buffer;
1439 path->slots[0] = 0;
Chris Masona429e512007-04-18 16:15:28 -04001440 if (path->slots[1] == 0) {
1441 wret = fixup_low_keys(trans, root,
1442 path, &disk_key, 1);
1443 if (wret)
1444 ret = wret;
1445 }
Chris Masond4dbff92007-04-04 14:08:15 -04001446 return ret;
1447 }
1448 mid = slot;
1449 double_split = 1;
1450 }
1451 }
1452 btrfs_set_header_nritems(&right->header, nritems - mid);
Chris Mason123abc82007-03-14 14:14:43 -04001453 data_copy_size = btrfs_item_end(l->items + mid) -
1454 leaf_data_end(root, l);
Chris Masond6025572007-03-30 14:27:56 -04001455 btrfs_memcpy(root, right, right->items, l->items + mid,
1456 (nritems - mid) * sizeof(struct btrfs_item));
1457 btrfs_memcpy(root, right,
1458 btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) -
1459 data_copy_size, btrfs_leaf_data(l) +
1460 leaf_data_end(root, l), data_copy_size);
Chris Mason123abc82007-03-14 14:14:43 -04001461 rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
1462 btrfs_item_end(l->items + mid);
Chris Mason74123bd2007-02-02 11:05:29 -05001463
Chris Mason0783fcf2007-03-12 20:12:07 -04001464 for (i = 0; i < btrfs_header_nritems(&right->header); i++) {
Chris Mason123abc82007-03-14 14:14:43 -04001465 u32 ioff = btrfs_item_offset(right->items + i);
Chris Mason0783fcf2007-03-12 20:12:07 -04001466 btrfs_set_item_offset(right->items + i, ioff + rt_data_off);
1467 }
Chris Mason74123bd2007-02-02 11:05:29 -05001468
Chris Mason7518a232007-03-12 12:01:18 -04001469 btrfs_set_header_nritems(&l->header, mid);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001470 ret = 0;
Chris Masone089f052007-03-16 16:20:31 -04001471 wret = insert_ptr(trans, root, path, &right->items[0].key,
Chris Mason7eccb902007-04-11 15:53:25 -04001472 bh_blocknr(right_buffer), path->slots[1] + 1, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001473 if (wret)
1474 ret = wret;
Chris Masond6025572007-03-30 14:27:56 -04001475 btrfs_mark_buffer_dirty(right_buffer);
1476 btrfs_mark_buffer_dirty(l_buf);
Chris Masoneb60cea2007-02-02 09:18:22 -05001477 BUG_ON(path->slots[0] != slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001478 if (mid <= slot) {
Chris Mason234b63a2007-03-13 10:46:10 -04001479 btrfs_block_release(root, path->nodes[0]);
Chris Masoneb60cea2007-02-02 09:18:22 -05001480 path->nodes[0] = right_buffer;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001481 path->slots[0] -= mid;
1482 path->slots[1] += 1;
Chris Masoneb60cea2007-02-02 09:18:22 -05001483 } else
Chris Mason234b63a2007-03-13 10:46:10 -04001484 btrfs_block_release(root, right_buffer);
Chris Masoneb60cea2007-02-02 09:18:22 -05001485 BUG_ON(path->slots[0] < 0);
Chris Mason098f59c2007-05-11 11:33:21 -04001486 check_node(root, path, 1);
Chris Masond4dbff92007-04-04 14:08:15 -04001487
1488 if (!double_split)
1489 return ret;
Chris Mason31f3c992007-04-30 15:25:45 -04001490 right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr);
Chris Mason54aa1f42007-06-22 14:16:25 -04001491 if (IS_ERR(right_buffer))
1492 return PTR_ERR(right_buffer);
1493
Chris Masond4dbff92007-04-04 14:08:15 -04001494 right = btrfs_buffer_leaf(right_buffer);
1495 memset(&right->header, 0, sizeof(right->header));
Chris Mason7eccb902007-04-11 15:53:25 -04001496 btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer));
Chris Masond4dbff92007-04-04 14:08:15 -04001497 btrfs_set_header_generation(&right->header, trans->transid);
Chris Mason4d775672007-04-20 20:23:12 -04001498 btrfs_set_header_owner(&right->header, root->root_key.objectid);
Chris Masond4dbff92007-04-04 14:08:15 -04001499 btrfs_set_header_level(&right->header, 0);
Chris Mason3eb03142007-04-05 14:28:50 -04001500 memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
1501 sizeof(right->header.fsid));
Chris Masond4dbff92007-04-04 14:08:15 -04001502 btrfs_cpu_key_to_disk(&disk_key, ins_key);
1503 btrfs_set_header_nritems(&right->header, 0);
1504 wret = insert_ptr(trans, root, path,
1505 &disk_key,
Chris Mason7eccb902007-04-11 15:53:25 -04001506 bh_blocknr(right_buffer),
Chris Masond4dbff92007-04-04 14:08:15 -04001507 path->slots[1], 1);
1508 if (wret)
1509 ret = wret;
Chris Masona429e512007-04-18 16:15:28 -04001510 if (path->slots[1] == 0) {
1511 wret = fixup_low_keys(trans, root, path, &disk_key, 1);
1512 if (wret)
1513 ret = wret;
1514 }
Chris Masond4dbff92007-04-04 14:08:15 -04001515 btrfs_block_release(root, path->nodes[0]);
1516 path->nodes[0] = right_buffer;
1517 path->slots[0] = 0;
1518 check_node(root, path, 1);
1519 check_leaf(root, path, 0);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001520 return ret;
1521}
1522
Chris Masonb18c6682007-04-17 13:26:50 -04001523int btrfs_truncate_item(struct btrfs_trans_handle *trans,
1524 struct btrfs_root *root,
1525 struct btrfs_path *path,
1526 u32 new_size)
1527{
1528 int ret = 0;
1529 int slot;
1530 int slot_orig;
1531 struct btrfs_leaf *leaf;
1532 struct buffer_head *leaf_buf;
1533 u32 nritems;
1534 unsigned int data_end;
1535 unsigned int old_data_start;
1536 unsigned int old_size;
1537 unsigned int size_diff;
1538 int i;
1539
1540 slot_orig = path->slots[0];
1541 leaf_buf = path->nodes[0];
1542 leaf = btrfs_buffer_leaf(leaf_buf);
1543
1544 nritems = btrfs_header_nritems(&leaf->header);
1545 data_end = leaf_data_end(root, leaf);
1546
1547 slot = path->slots[0];
1548 old_data_start = btrfs_item_offset(leaf->items + slot);
1549 old_size = btrfs_item_size(leaf->items + slot);
1550 BUG_ON(old_size <= new_size);
1551 size_diff = old_size - new_size;
1552
1553 BUG_ON(slot < 0);
1554 BUG_ON(slot >= nritems);
1555
1556 /*
1557 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1558 */
1559 /* first correct the data pointers */
1560 for (i = slot; i < nritems; i++) {
1561 u32 ioff = btrfs_item_offset(leaf->items + i);
1562 btrfs_set_item_offset(leaf->items + i,
1563 ioff + size_diff);
1564 }
1565 /* shift the data */
Chris Masonb18c6682007-04-17 13:26:50 -04001566 btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1567 data_end + size_diff, btrfs_leaf_data(leaf) +
1568 data_end, old_data_start + new_size - data_end);
1569 btrfs_set_item_size(leaf->items + slot, new_size);
1570 btrfs_mark_buffer_dirty(leaf_buf);
1571
1572 ret = 0;
1573 if (btrfs_leaf_free_space(root, leaf) < 0)
1574 BUG();
1575 check_leaf(root, path, 0);
1576 return ret;
1577}
1578
Chris Mason6567e832007-04-16 09:22:45 -04001579int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
1580 *root, struct btrfs_path *path, u32 data_size)
1581{
1582 int ret = 0;
1583 int slot;
1584 int slot_orig;
1585 struct btrfs_leaf *leaf;
1586 struct buffer_head *leaf_buf;
1587 u32 nritems;
1588 unsigned int data_end;
1589 unsigned int old_data;
1590 unsigned int old_size;
1591 int i;
1592
1593 slot_orig = path->slots[0];
1594 leaf_buf = path->nodes[0];
1595 leaf = btrfs_buffer_leaf(leaf_buf);
1596
1597 nritems = btrfs_header_nritems(&leaf->header);
1598 data_end = leaf_data_end(root, leaf);
1599
1600 if (btrfs_leaf_free_space(root, leaf) < data_size)
1601 BUG();
1602 slot = path->slots[0];
1603 old_data = btrfs_item_end(leaf->items + slot);
1604
1605 BUG_ON(slot < 0);
1606 BUG_ON(slot >= nritems);
1607
1608 /*
1609 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1610 */
1611 /* first correct the data pointers */
1612 for (i = slot; i < nritems; i++) {
1613 u32 ioff = btrfs_item_offset(leaf->items + i);
1614 btrfs_set_item_offset(leaf->items + i,
1615 ioff - data_size);
1616 }
1617 /* shift the data */
1618 btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1619 data_end - data_size, btrfs_leaf_data(leaf) +
1620 data_end, old_data - data_end);
1621 data_end = old_data;
1622 old_size = btrfs_item_size(leaf->items + slot);
1623 btrfs_set_item_size(leaf->items + slot, old_size + data_size);
1624 btrfs_mark_buffer_dirty(leaf_buf);
1625
1626 ret = 0;
1627 if (btrfs_leaf_free_space(root, leaf) < 0)
1628 BUG();
1629 check_leaf(root, path, 0);
1630 return ret;
1631}
1632
Chris Mason74123bd2007-02-02 11:05:29 -05001633/*
1634 * Given a key and some data, insert an item into the tree.
1635 * This does all the path init required, making room in the tree if needed.
1636 */
Chris Masone089f052007-03-16 16:20:31 -04001637int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
1638 *root, struct btrfs_path *path, struct btrfs_key
1639 *cpu_key, u32 data_size)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001640{
Chris Masonaa5d6be2007-02-28 16:35:06 -05001641 int ret = 0;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001642 int slot;
Chris Masoneb60cea2007-02-02 09:18:22 -05001643 int slot_orig;
Chris Mason234b63a2007-03-13 10:46:10 -04001644 struct btrfs_leaf *leaf;
Chris Masone20d96d2007-03-22 12:13:20 -04001645 struct buffer_head *leaf_buf;
Chris Mason7518a232007-03-12 12:01:18 -04001646 u32 nritems;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001647 unsigned int data_end;
Chris Masone2fa7222007-03-12 16:22:34 -04001648 struct btrfs_disk_key disk_key;
1649
1650 btrfs_cpu_key_to_disk(&disk_key, cpu_key);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001651
Chris Mason74123bd2007-02-02 11:05:29 -05001652 /* create a root if there isn't one */
Chris Mason5c680ed2007-02-22 11:39:13 -05001653 if (!root->node)
Chris Masoncfaa7292007-02-21 17:04:57 -05001654 BUG();
Chris Masone089f052007-03-16 16:20:31 -04001655 ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
Chris Masoneb60cea2007-02-02 09:18:22 -05001656 if (ret == 0) {
Chris Masonf0930a32007-03-02 09:47:58 -05001657 return -EEXIST;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001658 }
Chris Masoned2ff2c2007-03-01 18:59:40 -05001659 if (ret < 0)
1660 goto out;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001661
Chris Mason62e27492007-03-15 12:56:47 -04001662 slot_orig = path->slots[0];
1663 leaf_buf = path->nodes[0];
Chris Masone20d96d2007-03-22 12:13:20 -04001664 leaf = btrfs_buffer_leaf(leaf_buf);
Chris Mason74123bd2007-02-02 11:05:29 -05001665
Chris Mason7518a232007-03-12 12:01:18 -04001666 nritems = btrfs_header_nritems(&leaf->header);
Chris Mason123abc82007-03-14 14:14:43 -04001667 data_end = leaf_data_end(root, leaf);
Chris Masoneb60cea2007-02-02 09:18:22 -05001668
Chris Mason123abc82007-03-14 14:14:43 -04001669 if (btrfs_leaf_free_space(root, leaf) <
Chris Masond4dbff92007-04-04 14:08:15 -04001670 sizeof(struct btrfs_item) + data_size) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001671 BUG();
Chris Masond4dbff92007-04-04 14:08:15 -04001672 }
Chris Mason62e27492007-03-15 12:56:47 -04001673 slot = path->slots[0];
Chris Masoneb60cea2007-02-02 09:18:22 -05001674 BUG_ON(slot < 0);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001675 if (slot != nritems) {
1676 int i;
Chris Mason0783fcf2007-03-12 20:12:07 -04001677 unsigned int old_data = btrfs_item_end(leaf->items + slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001678
1679 /*
1680 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1681 */
1682 /* first correct the data pointers */
Chris Mason0783fcf2007-03-12 20:12:07 -04001683 for (i = slot; i < nritems; i++) {
Chris Mason123abc82007-03-14 14:14:43 -04001684 u32 ioff = btrfs_item_offset(leaf->items + i);
Chris Mason0783fcf2007-03-12 20:12:07 -04001685 btrfs_set_item_offset(leaf->items + i,
1686 ioff - data_size);
1687 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05001688
1689 /* shift the items */
Chris Masond6025572007-03-30 14:27:56 -04001690 btrfs_memmove(root, leaf, leaf->items + slot + 1,
1691 leaf->items + slot,
1692 (nritems - slot) * sizeof(struct btrfs_item));
Chris Masonbe0e5c02007-01-26 15:51:26 -05001693
1694 /* shift the data */
Chris Masond6025572007-03-30 14:27:56 -04001695 btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1696 data_end - data_size, btrfs_leaf_data(leaf) +
1697 data_end, old_data - data_end);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001698 data_end = old_data;
1699 }
Chris Mason62e27492007-03-15 12:56:47 -04001700 /* setup the item for the new data */
Chris Masond6025572007-03-30 14:27:56 -04001701 btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key,
1702 sizeof(struct btrfs_disk_key));
Chris Mason0783fcf2007-03-12 20:12:07 -04001703 btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
1704 btrfs_set_item_size(leaf->items + slot, data_size);
Chris Mason7518a232007-03-12 12:01:18 -04001705 btrfs_set_header_nritems(&leaf->header, nritems + 1);
Chris Masond6025572007-03-30 14:27:56 -04001706 btrfs_mark_buffer_dirty(leaf_buf);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001707
1708 ret = 0;
Chris Mason8e19f2c2007-02-28 09:27:02 -05001709 if (slot == 0)
Chris Masone089f052007-03-16 16:20:31 -04001710 ret = fixup_low_keys(trans, root, path, &disk_key, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001711
Chris Mason123abc82007-03-14 14:14:43 -04001712 if (btrfs_leaf_free_space(root, leaf) < 0)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001713 BUG();
Chris Mason62e27492007-03-15 12:56:47 -04001714 check_leaf(root, path, 0);
Chris Masoned2ff2c2007-03-01 18:59:40 -05001715out:
Chris Mason62e27492007-03-15 12:56:47 -04001716 return ret;
1717}
1718
1719/*
1720 * Given a key and some data, insert an item into the tree.
1721 * This does all the path init required, making room in the tree if needed.
1722 */
Chris Masone089f052007-03-16 16:20:31 -04001723int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
1724 *root, struct btrfs_key *cpu_key, void *data, u32
1725 data_size)
Chris Mason62e27492007-03-15 12:56:47 -04001726{
1727 int ret = 0;
Chris Mason2c90e5d2007-04-02 10:50:19 -04001728 struct btrfs_path *path;
Chris Mason62e27492007-03-15 12:56:47 -04001729 u8 *ptr;
1730
Chris Mason2c90e5d2007-04-02 10:50:19 -04001731 path = btrfs_alloc_path();
1732 BUG_ON(!path);
Chris Mason2c90e5d2007-04-02 10:50:19 -04001733 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
Chris Mason62e27492007-03-15 12:56:47 -04001734 if (!ret) {
Chris Mason2c90e5d2007-04-02 10:50:19 -04001735 ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
1736 path->slots[0], u8);
1737 btrfs_memcpy(root, path->nodes[0]->b_data,
Chris Masond6025572007-03-30 14:27:56 -04001738 ptr, data, data_size);
Chris Mason2c90e5d2007-04-02 10:50:19 -04001739 btrfs_mark_buffer_dirty(path->nodes[0]);
Chris Mason62e27492007-03-15 12:56:47 -04001740 }
Chris Mason2c90e5d2007-04-02 10:50:19 -04001741 btrfs_free_path(path);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001742 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001743}
1744
Chris Mason74123bd2007-02-02 11:05:29 -05001745/*
Chris Mason5de08d72007-02-24 06:24:44 -05001746 * delete the pointer from a given node.
Chris Mason74123bd2007-02-02 11:05:29 -05001747 *
1748 * If the delete empties a node, the node is removed from the tree,
1749 * continuing all the way the root if required. The root is converted into
1750 * a leaf if all the nodes are emptied.
1751 */
Chris Masone089f052007-03-16 16:20:31 -04001752static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1753 struct btrfs_path *path, int level, int slot)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001754{
Chris Mason234b63a2007-03-13 10:46:10 -04001755 struct btrfs_node *node;
Chris Masone20d96d2007-03-22 12:13:20 -04001756 struct buffer_head *parent = path->nodes[level];
Chris Mason7518a232007-03-12 12:01:18 -04001757 u32 nritems;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001758 int ret = 0;
Chris Masonbb803952007-03-01 12:04:21 -05001759 int wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001760
Chris Masone20d96d2007-03-22 12:13:20 -04001761 node = btrfs_buffer_node(parent);
Chris Mason7518a232007-03-12 12:01:18 -04001762 nritems = btrfs_header_nritems(&node->header);
Chris Masonbb803952007-03-01 12:04:21 -05001763 if (slot != nritems -1) {
Chris Masond6025572007-03-30 14:27:56 -04001764 btrfs_memmove(root, node, node->ptrs + slot,
1765 node->ptrs + slot + 1,
1766 sizeof(struct btrfs_key_ptr) *
1767 (nritems - slot - 1));
Chris Masonbb803952007-03-01 12:04:21 -05001768 }
Chris Mason7518a232007-03-12 12:01:18 -04001769 nritems--;
1770 btrfs_set_header_nritems(&node->header, nritems);
1771 if (nritems == 0 && parent == root->node) {
Chris Masone20d96d2007-03-22 12:13:20 -04001772 struct btrfs_header *header = btrfs_buffer_header(root->node);
1773 BUG_ON(btrfs_header_level(header) != 1);
Chris Masonbb803952007-03-01 12:04:21 -05001774 /* just turn the root into a leaf and break */
Chris Masone20d96d2007-03-22 12:13:20 -04001775 btrfs_set_header_level(header, 0);
Chris Masonbb803952007-03-01 12:04:21 -05001776 } else if (slot == 0) {
Chris Masone089f052007-03-16 16:20:31 -04001777 wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
Chris Mason123abc82007-03-14 14:14:43 -04001778 level + 1);
Chris Mason0f70abe2007-02-28 16:46:22 -05001779 if (wret)
1780 ret = wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001781 }
Chris Masond6025572007-03-30 14:27:56 -04001782 btrfs_mark_buffer_dirty(parent);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001783 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001784}
1785
Chris Mason74123bd2007-02-02 11:05:29 -05001786/*
1787 * delete the item at the leaf level in path. If that empties
1788 * the leaf, remove it from the tree
1789 */
Chris Masone089f052007-03-16 16:20:31 -04001790int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1791 struct btrfs_path *path)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001792{
Chris Masonbe0e5c02007-01-26 15:51:26 -05001793 int slot;
Chris Mason234b63a2007-03-13 10:46:10 -04001794 struct btrfs_leaf *leaf;
Chris Masone20d96d2007-03-22 12:13:20 -04001795 struct buffer_head *leaf_buf;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001796 int doff;
1797 int dsize;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001798 int ret = 0;
1799 int wret;
Chris Mason7518a232007-03-12 12:01:18 -04001800 u32 nritems;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001801
Chris Masoneb60cea2007-02-02 09:18:22 -05001802 leaf_buf = path->nodes[0];
Chris Masone20d96d2007-03-22 12:13:20 -04001803 leaf = btrfs_buffer_leaf(leaf_buf);
Chris Mason4920c9a2007-01-26 16:38:42 -05001804 slot = path->slots[0];
Chris Mason0783fcf2007-03-12 20:12:07 -04001805 doff = btrfs_item_offset(leaf->items + slot);
1806 dsize = btrfs_item_size(leaf->items + slot);
Chris Mason7518a232007-03-12 12:01:18 -04001807 nritems = btrfs_header_nritems(&leaf->header);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001808
Chris Mason7518a232007-03-12 12:01:18 -04001809 if (slot != nritems - 1) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001810 int i;
Chris Mason123abc82007-03-14 14:14:43 -04001811 int data_end = leaf_data_end(root, leaf);
Chris Masond6025572007-03-30 14:27:56 -04001812 btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) +
1813 data_end + dsize,
1814 btrfs_leaf_data(leaf) + data_end,
1815 doff - data_end);
Chris Mason0783fcf2007-03-12 20:12:07 -04001816 for (i = slot + 1; i < nritems; i++) {
Chris Mason123abc82007-03-14 14:14:43 -04001817 u32 ioff = btrfs_item_offset(leaf->items + i);
Chris Mason0783fcf2007-03-12 20:12:07 -04001818 btrfs_set_item_offset(leaf->items + i, ioff + dsize);
1819 }
Chris Masond6025572007-03-30 14:27:56 -04001820 btrfs_memmove(root, leaf, leaf->items + slot,
1821 leaf->items + slot + 1,
1822 sizeof(struct btrfs_item) *
1823 (nritems - slot - 1));
Chris Masonbe0e5c02007-01-26 15:51:26 -05001824 }
Chris Mason7518a232007-03-12 12:01:18 -04001825 btrfs_set_header_nritems(&leaf->header, nritems - 1);
1826 nritems--;
Chris Mason74123bd2007-02-02 11:05:29 -05001827 /* delete the leaf if we've emptied it */
Chris Mason7518a232007-03-12 12:01:18 -04001828 if (nritems == 0) {
Chris Masoneb60cea2007-02-02 09:18:22 -05001829 if (leaf_buf == root->node) {
Chris Mason7518a232007-03-12 12:01:18 -04001830 btrfs_set_header_level(&leaf->header, 0);
Chris Mason9a8dd152007-02-23 08:38:36 -05001831 } else {
Chris Masone089f052007-03-16 16:20:31 -04001832 clean_tree_block(trans, root, leaf_buf);
Chris Masond6025572007-03-30 14:27:56 -04001833 wait_on_buffer(leaf_buf);
Chris Masone089f052007-03-16 16:20:31 -04001834 wret = del_ptr(trans, root, path, 1, path->slots[1]);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001835 if (wret)
1836 ret = wret;
Chris Masone089f052007-03-16 16:20:31 -04001837 wret = btrfs_free_extent(trans, root,
Chris Mason7eccb902007-04-11 15:53:25 -04001838 bh_blocknr(leaf_buf), 1, 1);
Chris Mason0f70abe2007-02-28 16:46:22 -05001839 if (wret)
1840 ret = wret;
Chris Mason9a8dd152007-02-23 08:38:36 -05001841 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05001842 } else {
Chris Mason7518a232007-03-12 12:01:18 -04001843 int used = leaf_space_used(leaf, 0, nritems);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001844 if (slot == 0) {
Chris Masone089f052007-03-16 16:20:31 -04001845 wret = fixup_low_keys(trans, root, path,
1846 &leaf->items[0].key, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001847 if (wret)
1848 ret = wret;
1849 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001850
Chris Mason74123bd2007-02-02 11:05:29 -05001851 /* delete the leaf if it is mostly empty */
Chris Mason123abc82007-03-14 14:14:43 -04001852 if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001853 /* push_leaf_left fixes the path.
1854 * make sure the path still points to our leaf
1855 * for possible call to del_ptr below
1856 */
Chris Mason4920c9a2007-01-26 16:38:42 -05001857 slot = path->slots[1];
Chris Masone20d96d2007-03-22 12:13:20 -04001858 get_bh(leaf_buf);
Chris Masone089f052007-03-16 16:20:31 -04001859 wret = push_leaf_left(trans, root, path, 1);
Chris Mason54aa1f42007-06-22 14:16:25 -04001860 if (wret < 0 && wret != -ENOSPC)
Chris Masonaa5d6be2007-02-28 16:35:06 -05001861 ret = wret;
Chris Masonf0930a32007-03-02 09:47:58 -05001862 if (path->nodes[0] == leaf_buf &&
Chris Mason7518a232007-03-12 12:01:18 -04001863 btrfs_header_nritems(&leaf->header)) {
Chris Masone089f052007-03-16 16:20:31 -04001864 wret = push_leaf_right(trans, root, path, 1);
Chris Mason54aa1f42007-06-22 14:16:25 -04001865 if (wret < 0 && wret != -ENOSPC)
Chris Masonaa5d6be2007-02-28 16:35:06 -05001866 ret = wret;
1867 }
Chris Mason7518a232007-03-12 12:01:18 -04001868 if (btrfs_header_nritems(&leaf->header) == 0) {
Chris Mason7eccb902007-04-11 15:53:25 -04001869 u64 blocknr = bh_blocknr(leaf_buf);
Chris Masone089f052007-03-16 16:20:31 -04001870 clean_tree_block(trans, root, leaf_buf);
Chris Masond6025572007-03-30 14:27:56 -04001871 wait_on_buffer(leaf_buf);
Chris Masone089f052007-03-16 16:20:31 -04001872 wret = del_ptr(trans, root, path, 1, slot);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001873 if (wret)
1874 ret = wret;
Chris Mason234b63a2007-03-13 10:46:10 -04001875 btrfs_block_release(root, leaf_buf);
Chris Masone089f052007-03-16 16:20:31 -04001876 wret = btrfs_free_extent(trans, root, blocknr,
1877 1, 1);
Chris Mason0f70abe2007-02-28 16:46:22 -05001878 if (wret)
1879 ret = wret;
Chris Mason5de08d72007-02-24 06:24:44 -05001880 } else {
Chris Masond6025572007-03-30 14:27:56 -04001881 btrfs_mark_buffer_dirty(leaf_buf);
Chris Mason234b63a2007-03-13 10:46:10 -04001882 btrfs_block_release(root, leaf_buf);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001883 }
Chris Masond5719762007-03-23 10:01:08 -04001884 } else {
Chris Masond6025572007-03-30 14:27:56 -04001885 btrfs_mark_buffer_dirty(leaf_buf);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001886 }
1887 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001888 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001889}
1890
Chris Mason97571fd2007-02-24 13:39:08 -05001891/*
1892 * walk up the tree as far as required to find the next leaf.
Chris Mason0f70abe2007-02-28 16:46:22 -05001893 * returns 0 if it found something or 1 if there are no greater leaves.
1894 * returns < 0 on io errors.
Chris Mason97571fd2007-02-24 13:39:08 -05001895 */
Chris Mason234b63a2007-03-13 10:46:10 -04001896int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
Chris Masond97e63b2007-02-20 16:40:44 -05001897{
1898 int slot;
1899 int level = 1;
1900 u64 blocknr;
Chris Masone20d96d2007-03-22 12:13:20 -04001901 struct buffer_head *c;
1902 struct btrfs_node *c_node;
1903 struct buffer_head *next = NULL;
Chris Masond97e63b2007-02-20 16:40:44 -05001904
Chris Mason234b63a2007-03-13 10:46:10 -04001905 while(level < BTRFS_MAX_LEVEL) {
Chris Masond97e63b2007-02-20 16:40:44 -05001906 if (!path->nodes[level])
Chris Mason0f70abe2007-02-28 16:46:22 -05001907 return 1;
Chris Masond97e63b2007-02-20 16:40:44 -05001908 slot = path->slots[level] + 1;
1909 c = path->nodes[level];
Chris Masone20d96d2007-03-22 12:13:20 -04001910 c_node = btrfs_buffer_node(c);
1911 if (slot >= btrfs_header_nritems(&c_node->header)) {
Chris Masond97e63b2007-02-20 16:40:44 -05001912 level++;
1913 continue;
1914 }
Chris Masone20d96d2007-03-22 12:13:20 -04001915 blocknr = btrfs_node_blockptr(c_node, slot);
Chris Masoncfaa7292007-02-21 17:04:57 -05001916 if (next)
Chris Mason234b63a2007-03-13 10:46:10 -04001917 btrfs_block_release(root, next);
Chris Masond97e63b2007-02-20 16:40:44 -05001918 next = read_tree_block(root, blocknr);
1919 break;
1920 }
1921 path->slots[level] = slot;
1922 while(1) {
1923 level--;
1924 c = path->nodes[level];
Chris Mason234b63a2007-03-13 10:46:10 -04001925 btrfs_block_release(root, c);
Chris Masond97e63b2007-02-20 16:40:44 -05001926 path->nodes[level] = next;
1927 path->slots[level] = 0;
1928 if (!level)
1929 break;
Chris Mason1d4f8a02007-03-13 09:28:32 -04001930 next = read_tree_block(root,
Chris Masone20d96d2007-03-22 12:13:20 -04001931 btrfs_node_blockptr(btrfs_buffer_node(next), 0));
Chris Masond97e63b2007-02-20 16:40:44 -05001932 }
1933 return 0;
1934}