blob: 50ef351ef6b356eab786961ce68be74fe1c030fc [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 Mason5f39d392007-10-15 16:14:19 -040019#include <linux/highmem.h>
Chris Masoneb60cea2007-02-02 09:18:22 -050020#include "ctree.h"
21#include "disk-io.h"
Chris Mason7f5c1512007-03-23 15:56:19 -040022#include "transaction.h"
Chris Mason5f39d392007-10-15 16:14:19 -040023#include "print-tree.h"
Chris Mason9a8dd152007-02-23 08:38:36 -050024
Chris Masone089f052007-03-16 16:20:31 -040025static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
26 *root, struct btrfs_path *path, int level);
27static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masond4dbff92007-04-04 14:08:15 -040028 *root, struct btrfs_key *ins_key,
29 struct btrfs_path *path, int data_size);
Chris Mason5f39d392007-10-15 16:14:19 -040030static int push_node_left(struct btrfs_trans_handle *trans,
31 struct btrfs_root *root, struct extent_buffer *dst,
32 struct extent_buffer *src);
33static int balance_node_right(struct btrfs_trans_handle *trans,
34 struct btrfs_root *root,
35 struct extent_buffer *dst_buf,
36 struct extent_buffer *src_buf);
Chris Masone089f052007-03-16 16:20:31 -040037static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
38 struct btrfs_path *path, int level, int slot);
Chris Masond97e63b2007-02-20 16:40:44 -050039
Chris Masondf24a2b2007-04-04 09:36:31 -040040inline void btrfs_init_path(struct btrfs_path *p)
41{
42 memset(p, 0, sizeof(*p));
43}
44
Chris Mason2c90e5d2007-04-02 10:50:19 -040045struct btrfs_path *btrfs_alloc_path(void)
46{
Chris Masondf24a2b2007-04-04 09:36:31 -040047 struct btrfs_path *path;
48 path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
Chris Mason2cc58cf2007-08-27 16:49:44 -040049 if (path) {
Chris Masondf24a2b2007-04-04 09:36:31 -040050 btrfs_init_path(path);
Chris Mason2cc58cf2007-08-27 16:49:44 -040051 path->reada = 1;
52 }
Chris Masondf24a2b2007-04-04 09:36:31 -040053 return path;
Chris Mason2c90e5d2007-04-02 10:50:19 -040054}
55
56void btrfs_free_path(struct btrfs_path *p)
57{
Chris Masondf24a2b2007-04-04 09:36:31 -040058 btrfs_release_path(NULL, p);
Chris Mason2c90e5d2007-04-02 10:50:19 -040059 kmem_cache_free(btrfs_path_cachep, p);
60}
61
Chris Mason234b63a2007-03-13 10:46:10 -040062void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
Chris Masoneb60cea2007-02-02 09:18:22 -050063{
64 int i;
Chris Mason234b63a2007-03-13 10:46:10 -040065 for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
Chris Masoneb60cea2007-02-02 09:18:22 -050066 if (!p->nodes[i])
67 break;
Chris Mason5f39d392007-10-15 16:14:19 -040068 free_extent_buffer(p->nodes[i]);
Chris Masoneb60cea2007-02-02 09:18:22 -050069 }
Chris Masonaa5d6be2007-02-28 16:35:06 -050070 memset(p, 0, sizeof(*p));
Chris Masoneb60cea2007-02-02 09:18:22 -050071}
72
Chris Mason5f39d392007-10-15 16:14:19 -040073static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
74 struct btrfs_root *root,
75 struct extent_buffer *buf,
76 struct extent_buffer *parent, int parent_slot,
77 struct extent_buffer **cow_ret,
78 u64 search_start, u64 empty_size)
Chris Mason6702ed42007-08-07 16:15:09 -040079{
Chris Mason5f39d392007-10-15 16:14:19 -040080 struct extent_buffer *cow;
Chris Mason6702ed42007-08-07 16:15:09 -040081 int ret = 0;
82 int different_trans = 0;
83
84 WARN_ON(root->ref_cows && trans->transid != root->last_trans);
Chris Mason5f39d392007-10-15 16:14:19 -040085
Chris Mason6702ed42007-08-07 16:15:09 -040086 cow = btrfs_alloc_free_block(trans, root, search_start, empty_size);
87 if (IS_ERR(cow))
88 return PTR_ERR(cow);
89
Chris Masonf510cfe2007-10-15 16:14:48 -040090 cow->alloc_addr = (unsigned long)__builtin_return_address(0);
Chris Mason5f39d392007-10-15 16:14:19 -040091 if (buf->len != root->sectorsize || cow->len != root->sectorsize)
Chris Mason6702ed42007-08-07 16:15:09 -040092 WARN_ON(1);
93
Chris Mason5f39d392007-10-15 16:14:19 -040094 copy_extent_buffer(cow, buf, 0, 0, cow->len);
95 btrfs_set_header_blocknr(cow, extent_buffer_blocknr(cow));
96 btrfs_set_header_generation(cow, trans->transid);
97 btrfs_set_header_owner(cow, root->root_key.objectid);
Chris Mason6702ed42007-08-07 16:15:09 -040098
Chris Mason5f39d392007-10-15 16:14:19 -040099 WARN_ON(btrfs_header_generation(buf) > trans->transid);
100 if (btrfs_header_generation(buf) != trans->transid) {
Chris Mason6702ed42007-08-07 16:15:09 -0400101 different_trans = 1;
102 ret = btrfs_inc_ref(trans, root, buf);
103 if (ret)
104 return ret;
105 } else {
Chris Mason6702ed42007-08-07 16:15:09 -0400106 clean_tree_block(trans, root, buf);
107 }
108
109 if (buf == root->node) {
110 root->node = cow;
Chris Mason5f39d392007-10-15 16:14:19 -0400111 extent_buffer_get(cow);
Chris Mason6702ed42007-08-07 16:15:09 -0400112 if (buf != root->commit_root) {
Chris Mason5f39d392007-10-15 16:14:19 -0400113 btrfs_free_extent(trans, root,
114 extent_buffer_blocknr(buf), 1, 1);
Chris Mason6702ed42007-08-07 16:15:09 -0400115 }
Chris Mason5f39d392007-10-15 16:14:19 -0400116 free_extent_buffer(buf);
Chris Mason6702ed42007-08-07 16:15:09 -0400117 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400118 btrfs_set_node_blockptr(parent, parent_slot,
119 extent_buffer_blocknr(cow));
Chris Mason6702ed42007-08-07 16:15:09 -0400120 btrfs_mark_buffer_dirty(parent);
Chris Mason5f39d392007-10-15 16:14:19 -0400121 WARN_ON(btrfs_header_generation(parent) != trans->transid);
122 btrfs_free_extent(trans, root, extent_buffer_blocknr(buf),1,1);
Chris Mason6702ed42007-08-07 16:15:09 -0400123 }
Chris Mason5f39d392007-10-15 16:14:19 -0400124 free_extent_buffer(buf);
Chris Mason6702ed42007-08-07 16:15:09 -0400125 btrfs_mark_buffer_dirty(cow);
126 *cow_ret = cow;
127 return 0;
128}
129
Chris Mason5f39d392007-10-15 16:14:19 -0400130int btrfs_cow_block(struct btrfs_trans_handle *trans,
131 struct btrfs_root *root, struct extent_buffer *buf,
132 struct extent_buffer *parent, int parent_slot,
133 struct extent_buffer **cow_ret)
Chris Mason02217ed2007-03-02 16:08:05 -0500134{
Chris Mason6702ed42007-08-07 16:15:09 -0400135 u64 search_start;
Chris Masonf510cfe2007-10-15 16:14:48 -0400136 int ret;
Chris Masonccd467d2007-06-28 15:57:36 -0400137 if (trans->transaction != root->fs_info->running_transaction) {
138 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
139 root->fs_info->running_transaction->transid);
140 WARN_ON(1);
141 }
142 if (trans->transid != root->fs_info->generation) {
143 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
144 root->fs_info->generation);
145 WARN_ON(1);
146 }
Chris Mason5f39d392007-10-15 16:14:19 -0400147 if (btrfs_header_generation(buf) == trans->transid) {
Chris Mason02217ed2007-03-02 16:08:05 -0500148 *cow_ret = buf;
149 return 0;
150 }
Chris Mason6702ed42007-08-07 16:15:09 -0400151
Chris Mason5f39d392007-10-15 16:14:19 -0400152 search_start = extent_buffer_blocknr(buf) & ~((u64)65535);
Chris Masonf510cfe2007-10-15 16:14:48 -0400153 ret = __btrfs_cow_block(trans, root, buf, parent,
Chris Mason6702ed42007-08-07 16:15:09 -0400154 parent_slot, cow_ret, search_start, 0);
Chris Masonf510cfe2007-10-15 16:14:48 -0400155 (*cow_ret)->alloc_addr = (unsigned long)__builtin_return_address(0);
156 return ret;
Chris Mason6702ed42007-08-07 16:15:09 -0400157}
158
159static int close_blocks(u64 blocknr, u64 other)
160{
161 if (blocknr < other && other - blocknr < 8)
162 return 1;
163 if (blocknr > other && blocknr - other < 8)
164 return 1;
Chris Mason02217ed2007-03-02 16:08:05 -0500165 return 0;
166}
167
Chris Mason5f39d392007-10-15 16:14:19 -0400168#if 0
169static int should_defrag_leaf(struct extent_buffer *eb)
Chris Mason2cc58cf2007-08-27 16:49:44 -0400170{
Chris Mason5f39d392007-10-15 16:14:19 -0400171 return 0;
172 struct btrfs_leaf *leaf = btrfs_buffer_leaf(eb);
Chris Mason2cc58cf2007-08-27 16:49:44 -0400173 struct btrfs_disk_key *key;
174 u32 nritems;
175
176 if (buffer_defrag(bh))
177 return 1;
178
179 nritems = btrfs_header_nritems(&leaf->header);
180 if (nritems == 0)
181 return 0;
182
183 key = &leaf->items[0].key;
184 if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY)
185 return 1;
186
187 key = &leaf->items[nritems-1].key;
188 if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY)
189 return 1;
190 if (nritems > 4) {
191 key = &leaf->items[nritems/2].key;
192 if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY)
193 return 1;
194 }
195 return 0;
196}
Chris Mason5f39d392007-10-15 16:14:19 -0400197#endif
Chris Mason2cc58cf2007-08-27 16:49:44 -0400198
Chris Mason6702ed42007-08-07 16:15:09 -0400199int btrfs_realloc_node(struct btrfs_trans_handle *trans,
Chris Mason5f39d392007-10-15 16:14:19 -0400200 struct btrfs_root *root, struct extent_buffer *parent,
Chris Masone9d0b132007-08-10 14:06:19 -0400201 int cache_only, u64 *last_ret)
Chris Mason6702ed42007-08-07 16:15:09 -0400202{
Chris Mason5f39d392007-10-15 16:14:19 -0400203 return 0;
204#if 0
Chris Mason6702ed42007-08-07 16:15:09 -0400205 struct btrfs_node *parent_node;
Chris Mason5f39d392007-10-15 16:14:19 -0400206 struct extent_buffer *cur_eb;
207 struct extent_buffer *tmp_eb;
Chris Mason6702ed42007-08-07 16:15:09 -0400208 u64 blocknr;
Chris Masone9d0b132007-08-10 14:06:19 -0400209 u64 search_start = *last_ret;
210 u64 last_block = 0;
Chris Mason6702ed42007-08-07 16:15:09 -0400211 u64 other;
212 u32 parent_nritems;
213 int start_slot;
214 int end_slot;
215 int i;
216 int err = 0;
Chris Masonf2183bd2007-08-10 14:42:37 -0400217 int parent_level;
Chris Mason6702ed42007-08-07 16:15:09 -0400218
219 if (trans->transaction != root->fs_info->running_transaction) {
220 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
221 root->fs_info->running_transaction->transid);
222 WARN_ON(1);
223 }
224 if (trans->transid != root->fs_info->generation) {
225 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
226 root->fs_info->generation);
227 WARN_ON(1);
228 }
Chris Mason86479a02007-09-10 19:58:16 -0400229 if (buffer_defrag_done(parent))
230 return 0;
231
Chris Mason6702ed42007-08-07 16:15:09 -0400232 parent_node = btrfs_buffer_node(parent);
233 parent_nritems = btrfs_header_nritems(&parent_node->header);
Chris Masonf2183bd2007-08-10 14:42:37 -0400234 parent_level = btrfs_header_level(&parent_node->header);
Chris Mason6702ed42007-08-07 16:15:09 -0400235
236 start_slot = 0;
237 end_slot = parent_nritems;
238
239 if (parent_nritems == 1)
240 return 0;
241
242 for (i = start_slot; i < end_slot; i++) {
243 int close = 1;
244 blocknr = btrfs_node_blockptr(parent_node, i);
Chris Masone9d0b132007-08-10 14:06:19 -0400245 if (last_block == 0)
246 last_block = blocknr;
Chris Mason6702ed42007-08-07 16:15:09 -0400247 if (i > 0) {
248 other = btrfs_node_blockptr(parent_node, i - 1);
249 close = close_blocks(blocknr, other);
250 }
251 if (close && i < end_slot - 1) {
252 other = btrfs_node_blockptr(parent_node, i + 1);
253 close = close_blocks(blocknr, other);
254 }
Chris Masone9d0b132007-08-10 14:06:19 -0400255 if (close) {
256 last_block = blocknr;
Chris Mason6702ed42007-08-07 16:15:09 -0400257 continue;
Chris Masone9d0b132007-08-10 14:06:19 -0400258 }
Chris Mason6702ed42007-08-07 16:15:09 -0400259
260 cur_bh = btrfs_find_tree_block(root, blocknr);
261 if (!cur_bh || !buffer_uptodate(cur_bh) ||
Chris Mason2cc58cf2007-08-27 16:49:44 -0400262 buffer_locked(cur_bh) ||
263 (parent_level != 1 && !buffer_defrag(cur_bh)) ||
264 (parent_level == 1 && !should_defrag_leaf(cur_bh))) {
Chris Mason6702ed42007-08-07 16:15:09 -0400265 if (cache_only) {
266 brelse(cur_bh);
267 continue;
268 }
Chris Masonf2183bd2007-08-10 14:42:37 -0400269 if (!cur_bh || !buffer_uptodate(cur_bh) ||
270 buffer_locked(cur_bh)) {
271 brelse(cur_bh);
272 cur_bh = read_tree_block(root, blocknr);
273 }
Chris Mason6702ed42007-08-07 16:15:09 -0400274 }
Chris Masone9d0b132007-08-10 14:06:19 -0400275 if (search_start == 0)
276 search_start = last_block & ~((u64)65535);
277
Chris Mason6702ed42007-08-07 16:15:09 -0400278 err = __btrfs_cow_block(trans, root, cur_bh, parent, i,
279 &tmp_bh, search_start,
280 min(8, end_slot - i));
Yan252c38f2007-08-29 09:11:44 -0400281 if (err) {
282 brelse(cur_bh);
Chris Mason6702ed42007-08-07 16:15:09 -0400283 break;
Yan252c38f2007-08-29 09:11:44 -0400284 }
Chris Mason6702ed42007-08-07 16:15:09 -0400285 search_start = bh_blocknr(tmp_bh);
Chris Masonf2183bd2007-08-10 14:42:37 -0400286 *last_ret = search_start;
287 if (parent_level == 1)
288 clear_buffer_defrag(tmp_bh);
Chris Mason86479a02007-09-10 19:58:16 -0400289 set_buffer_defrag_done(tmp_bh);
Chris Mason6702ed42007-08-07 16:15:09 -0400290 brelse(tmp_bh);
291 }
292 return err;
Chris Mason5f39d392007-10-15 16:14:19 -0400293#endif
Chris Mason6702ed42007-08-07 16:15:09 -0400294}
295
Chris Mason74123bd2007-02-02 11:05:29 -0500296/*
297 * The leaf data grows from end-to-front in the node.
298 * this returns the address of the start of the last item,
299 * which is the stop of the leaf data stack
300 */
Chris Mason123abc82007-03-14 14:14:43 -0400301static inline unsigned int leaf_data_end(struct btrfs_root *root,
Chris Mason5f39d392007-10-15 16:14:19 -0400302 struct extent_buffer *leaf)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500303{
Chris Mason5f39d392007-10-15 16:14:19 -0400304 u32 nr = btrfs_header_nritems(leaf);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500305 if (nr == 0)
Chris Mason123abc82007-03-14 14:14:43 -0400306 return BTRFS_LEAF_DATA_SIZE(root);
Chris Mason5f39d392007-10-15 16:14:19 -0400307 return btrfs_item_offset_nr(leaf, nr - 1);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500308}
309
Chris Mason74123bd2007-02-02 11:05:29 -0500310/*
Chris Mason74123bd2007-02-02 11:05:29 -0500311 * compare two keys in a memcmp fashion
312 */
Chris Mason9aca1d52007-03-13 11:09:37 -0400313static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500314{
Chris Masone2fa7222007-03-12 16:22:34 -0400315 struct btrfs_key k1;
316
317 btrfs_disk_key_to_cpu(&k1, disk);
318
319 if (k1.objectid > k2->objectid)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500320 return 1;
Chris Masone2fa7222007-03-12 16:22:34 -0400321 if (k1.objectid < k2->objectid)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500322 return -1;
Chris Mason5f39d392007-10-15 16:14:19 -0400323 if (k1.type > k2->type)
Chris Masonf254e522007-03-29 15:15:27 -0400324 return 1;
Chris Mason5f39d392007-10-15 16:14:19 -0400325 if (k1.type < k2->type)
Chris Masonf254e522007-03-29 15:15:27 -0400326 return -1;
Chris Mason70b2bef2007-04-17 15:39:32 -0400327 if (k1.offset > k2->offset)
328 return 1;
329 if (k1.offset < k2->offset)
330 return -1;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500331 return 0;
332}
Chris Mason74123bd2007-02-02 11:05:29 -0500333
Chris Mason123abc82007-03-14 14:14:43 -0400334static int check_node(struct btrfs_root *root, struct btrfs_path *path,
335 int level)
Chris Masonaa5d6be2007-02-28 16:35:06 -0500336{
Chris Mason5f39d392007-10-15 16:14:19 -0400337 struct extent_buffer *parent = NULL;
338 struct extent_buffer *node = path->nodes[level];
339 struct btrfs_disk_key parent_key;
340 struct btrfs_disk_key node_key;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500341 int parent_slot;
Chris Mason8d7be552007-05-10 11:24:42 -0400342 int slot;
343 struct btrfs_key cpukey;
Chris Mason5f39d392007-10-15 16:14:19 -0400344 u32 nritems = btrfs_header_nritems(node);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500345
346 if (path->nodes[level + 1])
Chris Mason5f39d392007-10-15 16:14:19 -0400347 parent = path->nodes[level + 1];
Aneesha1f39632007-07-11 10:03:27 -0400348
Chris Mason8d7be552007-05-10 11:24:42 -0400349 slot = path->slots[level];
Chris Mason7518a232007-03-12 12:01:18 -0400350 BUG_ON(nritems == 0);
351 if (parent) {
Aneesha1f39632007-07-11 10:03:27 -0400352 parent_slot = path->slots[level + 1];
Chris Mason5f39d392007-10-15 16:14:19 -0400353 btrfs_node_key(parent, &parent_key, parent_slot);
354 btrfs_node_key(node, &node_key, 0);
355 BUG_ON(memcmp(&parent_key, &node_key,
Chris Masone2fa7222007-03-12 16:22:34 -0400356 sizeof(struct btrfs_disk_key)));
Chris Mason1d4f8a02007-03-13 09:28:32 -0400357 BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
Chris Mason5f39d392007-10-15 16:14:19 -0400358 btrfs_header_blocknr(node));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500359 }
Chris Mason123abc82007-03-14 14:14:43 -0400360 BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
Chris Mason8d7be552007-05-10 11:24:42 -0400361 if (slot != 0) {
Chris Mason5f39d392007-10-15 16:14:19 -0400362 btrfs_node_key_to_cpu(node, &cpukey, slot - 1);
363 btrfs_node_key(node, &node_key, slot);
364 BUG_ON(comp_keys(&node_key, &cpukey) <= 0);
Chris Mason8d7be552007-05-10 11:24:42 -0400365 }
366 if (slot < nritems - 1) {
Chris Mason5f39d392007-10-15 16:14:19 -0400367 btrfs_node_key_to_cpu(node, &cpukey, slot + 1);
368 btrfs_node_key(node, &node_key, slot);
369 BUG_ON(comp_keys(&node_key, &cpukey) >= 0);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500370 }
371 return 0;
372}
373
Chris Mason123abc82007-03-14 14:14:43 -0400374static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
375 int level)
Chris Masonaa5d6be2007-02-28 16:35:06 -0500376{
Chris Mason5f39d392007-10-15 16:14:19 -0400377 struct extent_buffer *leaf = path->nodes[level];
378 struct extent_buffer *parent = NULL;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500379 int parent_slot;
Chris Mason8d7be552007-05-10 11:24:42 -0400380 struct btrfs_key cpukey;
Chris Mason5f39d392007-10-15 16:14:19 -0400381 struct btrfs_disk_key parent_key;
382 struct btrfs_disk_key leaf_key;
383 int slot = path->slots[0];
Chris Mason8d7be552007-05-10 11:24:42 -0400384
Chris Mason5f39d392007-10-15 16:14:19 -0400385 u32 nritems = btrfs_header_nritems(leaf);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500386
387 if (path->nodes[level + 1])
Chris Mason5f39d392007-10-15 16:14:19 -0400388 parent = path->nodes[level + 1];
Chris Mason7518a232007-03-12 12:01:18 -0400389
390 if (nritems == 0)
391 return 0;
392
393 if (parent) {
Aneesha1f39632007-07-11 10:03:27 -0400394 parent_slot = path->slots[level + 1];
Chris Mason5f39d392007-10-15 16:14:19 -0400395 btrfs_node_key(parent, &parent_key, parent_slot);
396 btrfs_item_key(leaf, &leaf_key, 0);
Chris Mason6702ed42007-08-07 16:15:09 -0400397
Chris Mason5f39d392007-10-15 16:14:19 -0400398 BUG_ON(memcmp(&parent_key, &leaf_key,
Chris Masone2fa7222007-03-12 16:22:34 -0400399 sizeof(struct btrfs_disk_key)));
Chris Mason1d4f8a02007-03-13 09:28:32 -0400400 BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
Chris Mason5f39d392007-10-15 16:14:19 -0400401 btrfs_header_blocknr(leaf));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500402 }
Chris Mason5f39d392007-10-15 16:14:19 -0400403#if 0
404 for (i = 0; nritems > 1 && i < nritems - 2; i++) {
405 btrfs_item_key_to_cpu(leaf, &cpukey, i + 1);
406 btrfs_item_key(leaf, &leaf_key, i);
407 if (comp_keys(&leaf_key, &cpukey) >= 0) {
408 btrfs_print_leaf(root, leaf);
409 printk("slot %d offset bad key\n", i);
410 BUG_ON(1);
411 }
412 if (btrfs_item_offset_nr(leaf, i) !=
413 btrfs_item_end_nr(leaf, i + 1)) {
414 btrfs_print_leaf(root, leaf);
415 printk("slot %d offset bad\n", i);
416 BUG_ON(1);
417 }
418 if (i == 0) {
419 if (btrfs_item_offset_nr(leaf, i) +
420 btrfs_item_size_nr(leaf, i) !=
421 BTRFS_LEAF_DATA_SIZE(root)) {
422 btrfs_print_leaf(root, leaf);
423 printk("slot %d first offset bad\n", i);
424 BUG_ON(1);
425 }
426 }
427 }
428 if (nritems > 0) {
429 if (btrfs_item_size_nr(leaf, nritems - 1) > 4096) {
430 btrfs_print_leaf(root, leaf);
431 printk("slot %d bad size \n", nritems - 1);
432 BUG_ON(1);
433 }
434 }
435#endif
436 if (slot != 0 && slot < nritems - 1) {
437 btrfs_item_key(leaf, &leaf_key, slot);
438 btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1);
439 if (comp_keys(&leaf_key, &cpukey) <= 0) {
440 btrfs_print_leaf(root, leaf);
441 printk("slot %d offset bad key\n", slot);
442 BUG_ON(1);
443 }
444 if (btrfs_item_offset_nr(leaf, slot - 1) !=
445 btrfs_item_end_nr(leaf, slot)) {
446 btrfs_print_leaf(root, leaf);
447 printk("slot %d offset bad\n", slot);
448 BUG_ON(1);
449 }
Chris Masonaa5d6be2007-02-28 16:35:06 -0500450 }
Chris Mason8d7be552007-05-10 11:24:42 -0400451 if (slot < nritems - 1) {
Chris Mason5f39d392007-10-15 16:14:19 -0400452 btrfs_item_key(leaf, &leaf_key, slot);
453 btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1);
454 BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0);
455 if (btrfs_item_offset_nr(leaf, slot) !=
456 btrfs_item_end_nr(leaf, slot + 1)) {
457 btrfs_print_leaf(root, leaf);
458 printk("slot %d offset bad\n", slot);
459 BUG_ON(1);
460 }
Chris Mason8d7be552007-05-10 11:24:42 -0400461 }
Chris Mason5f39d392007-10-15 16:14:19 -0400462 BUG_ON(btrfs_item_offset_nr(leaf, 0) +
463 btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root));
Chris Masonaa5d6be2007-02-28 16:35:06 -0500464 return 0;
465}
466
Chris Mason123abc82007-03-14 14:14:43 -0400467static int check_block(struct btrfs_root *root, struct btrfs_path *path,
468 int level)
Chris Masonaa5d6be2007-02-28 16:35:06 -0500469{
Chris Mason5f39d392007-10-15 16:14:19 -0400470 struct extent_buffer *buf = path->nodes[level];
Chris Mason5f39d392007-10-15 16:14:19 -0400471
Chris Mason479965d2007-10-15 16:14:27 -0400472 if (memcmp_extent_buffer(buf, root->fs_info->fsid,
473 (unsigned long)btrfs_header_fsid(buf),
474 BTRFS_FSID_SIZE)) {
Chris Mason5f39d392007-10-15 16:14:19 -0400475 printk("warning bad block %Lu\n", buf->start);
Chris Mason479965d2007-10-15 16:14:27 -0400476 BUG();
Chris Mason5f39d392007-10-15 16:14:19 -0400477 }
Chris Masonaa5d6be2007-02-28 16:35:06 -0500478 if (level == 0)
Chris Mason123abc82007-03-14 14:14:43 -0400479 return check_leaf(root, path, level);
480 return check_node(root, path, level);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500481}
482
Chris Mason74123bd2007-02-02 11:05:29 -0500483/*
Chris Mason5f39d392007-10-15 16:14:19 -0400484 * search for key in the extent_buffer. The items start at offset p,
485 * and they are item_size apart. There are 'max' items in p.
486 *
Chris Mason74123bd2007-02-02 11:05:29 -0500487 * the slot in the array is returned via slot, and it points to
488 * the place where you would insert key if it is not found in
489 * the array.
490 *
491 * slot may point to max if the key is bigger than all of the keys
492 */
Chris Mason5f39d392007-10-15 16:14:19 -0400493static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
494 int item_size, struct btrfs_key *key,
495 int max, int *slot)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500496{
497 int low = 0;
498 int high = max;
499 int mid;
500 int ret;
Chris Mason479965d2007-10-15 16:14:27 -0400501 struct btrfs_disk_key *tmp = NULL;
Chris Mason5f39d392007-10-15 16:14:19 -0400502 struct btrfs_disk_key unaligned;
503 unsigned long offset;
504 char *map_token = NULL;
505 char *kaddr = NULL;
506 unsigned long map_start = 0;
507 unsigned long map_len = 0;
Chris Mason479965d2007-10-15 16:14:27 -0400508 int err;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500509
510 while(low < high) {
511 mid = (low + high) / 2;
Chris Mason5f39d392007-10-15 16:14:19 -0400512 offset = p + mid * item_size;
513
514 if (!map_token || offset < map_start ||
515 (offset + sizeof(struct btrfs_disk_key)) >
516 map_start + map_len) {
Chris Mason479965d2007-10-15 16:14:27 -0400517 if (map_token) {
Chris Mason5f39d392007-10-15 16:14:19 -0400518 unmap_extent_buffer(eb, map_token, KM_USER0);
Chris Mason479965d2007-10-15 16:14:27 -0400519 map_token = NULL;
520 }
521 err = map_extent_buffer(eb, offset,
522 sizeof(struct btrfs_disk_key),
523 &map_token, &kaddr,
524 &map_start, &map_len, KM_USER0);
Chris Mason5f39d392007-10-15 16:14:19 -0400525
Chris Mason479965d2007-10-15 16:14:27 -0400526 if (!err) {
527 tmp = (struct btrfs_disk_key *)(kaddr + offset -
528 map_start);
529 } else {
530 read_extent_buffer(eb, &unaligned,
531 offset, sizeof(unaligned));
532 tmp = &unaligned;
533 }
534
Chris Mason5f39d392007-10-15 16:14:19 -0400535 } else {
536 tmp = (struct btrfs_disk_key *)(kaddr + offset -
537 map_start);
538 }
Chris Masonbe0e5c02007-01-26 15:51:26 -0500539 ret = comp_keys(tmp, key);
540
541 if (ret < 0)
542 low = mid + 1;
543 else if (ret > 0)
544 high = mid;
545 else {
546 *slot = mid;
Chris Mason479965d2007-10-15 16:14:27 -0400547 if (map_token)
548 unmap_extent_buffer(eb, map_token, KM_USER0);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500549 return 0;
550 }
551 }
552 *slot = low;
Chris Mason5f39d392007-10-15 16:14:19 -0400553 if (map_token)
554 unmap_extent_buffer(eb, map_token, KM_USER0);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500555 return 1;
556}
557
Chris Mason97571fd2007-02-24 13:39:08 -0500558/*
559 * simple bin_search frontend that does the right thing for
560 * leaves vs nodes
561 */
Chris Mason5f39d392007-10-15 16:14:19 -0400562static int bin_search(struct extent_buffer *eb, struct btrfs_key *key,
563 int level, int *slot)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500564{
Chris Mason5f39d392007-10-15 16:14:19 -0400565 if (level == 0) {
566 return generic_bin_search(eb,
567 offsetof(struct btrfs_leaf, items),
Chris Mason0783fcf2007-03-12 20:12:07 -0400568 sizeof(struct btrfs_item),
Chris Mason5f39d392007-10-15 16:14:19 -0400569 key, btrfs_header_nritems(eb),
Chris Mason7518a232007-03-12 12:01:18 -0400570 slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500571 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400572 return generic_bin_search(eb,
573 offsetof(struct btrfs_node, ptrs),
Chris Mason123abc82007-03-14 14:14:43 -0400574 sizeof(struct btrfs_key_ptr),
Chris Mason5f39d392007-10-15 16:14:19 -0400575 key, btrfs_header_nritems(eb),
Chris Mason7518a232007-03-12 12:01:18 -0400576 slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -0500577 }
578 return -1;
579}
580
Chris Mason5f39d392007-10-15 16:14:19 -0400581static struct extent_buffer *read_node_slot(struct btrfs_root *root,
582 struct extent_buffer *parent, int slot)
Chris Masonbb803952007-03-01 12:04:21 -0500583{
Chris Masonbb803952007-03-01 12:04:21 -0500584 if (slot < 0)
585 return NULL;
Chris Mason5f39d392007-10-15 16:14:19 -0400586 if (slot >= btrfs_header_nritems(parent))
Chris Masonbb803952007-03-01 12:04:21 -0500587 return NULL;
Chris Mason5f39d392007-10-15 16:14:19 -0400588 return read_tree_block(root, btrfs_node_blockptr(parent, slot));
Chris Masonbb803952007-03-01 12:04:21 -0500589}
590
Chris Masone089f052007-03-16 16:20:31 -0400591static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
592 *root, struct btrfs_path *path, int level)
Chris Masonbb803952007-03-01 12:04:21 -0500593{
Chris Mason5f39d392007-10-15 16:14:19 -0400594 struct extent_buffer *right = NULL;
595 struct extent_buffer *mid;
596 struct extent_buffer *left = NULL;
597 struct extent_buffer *parent = NULL;
Chris Masonbb803952007-03-01 12:04:21 -0500598 int ret = 0;
599 int wret;
600 int pslot;
Chris Masonbb803952007-03-01 12:04:21 -0500601 int orig_slot = path->slots[level];
Chris Mason54aa1f42007-06-22 14:16:25 -0400602 int err_on_enospc = 0;
Chris Mason79f95c82007-03-01 15:16:26 -0500603 u64 orig_ptr;
Chris Masonbb803952007-03-01 12:04:21 -0500604
605 if (level == 0)
606 return 0;
607
Chris Mason5f39d392007-10-15 16:14:19 -0400608 mid = path->nodes[level];
Chris Mason1d4f8a02007-03-13 09:28:32 -0400609 orig_ptr = btrfs_node_blockptr(mid, orig_slot);
Chris Mason79f95c82007-03-01 15:16:26 -0500610
Chris Mason234b63a2007-03-13 10:46:10 -0400611 if (level < BTRFS_MAX_LEVEL - 1)
Chris Mason5f39d392007-10-15 16:14:19 -0400612 parent = path->nodes[level + 1];
Chris Masonbb803952007-03-01 12:04:21 -0500613 pslot = path->slots[level + 1];
614
Chris Mason40689472007-03-17 14:29:23 -0400615 /*
616 * deal with the case where there is only one pointer in the root
617 * by promoting the node below to a root
618 */
Chris Mason5f39d392007-10-15 16:14:19 -0400619 if (!parent) {
620 struct extent_buffer *child;
621 u64 blocknr = extent_buffer_blocknr(mid);
Chris Masonbb803952007-03-01 12:04:21 -0500622
Chris Mason5f39d392007-10-15 16:14:19 -0400623 if (btrfs_header_nritems(mid) != 1)
Chris Masonbb803952007-03-01 12:04:21 -0500624 return 0;
625
626 /* promote the child to a root */
Chris Mason5f39d392007-10-15 16:14:19 -0400627 child = read_node_slot(root, mid, 0);
Chris Masonbb803952007-03-01 12:04:21 -0500628 BUG_ON(!child);
629 root->node = child;
630 path->nodes[level] = NULL;
Chris Mason5f39d392007-10-15 16:14:19 -0400631 clean_tree_block(trans, root, mid);
632 wait_on_tree_block_writeback(root, mid);
Chris Masonbb803952007-03-01 12:04:21 -0500633 /* once for the path */
Chris Mason5f39d392007-10-15 16:14:19 -0400634 free_extent_buffer(mid);
Chris Masonbb803952007-03-01 12:04:21 -0500635 /* once for the root ptr */
Chris Mason5f39d392007-10-15 16:14:19 -0400636 free_extent_buffer(mid);
Chris Masone089f052007-03-16 16:20:31 -0400637 return btrfs_free_extent(trans, root, blocknr, 1, 1);
Chris Masonbb803952007-03-01 12:04:21 -0500638 }
Chris Mason5f39d392007-10-15 16:14:19 -0400639 if (btrfs_header_nritems(mid) >
Chris Mason123abc82007-03-14 14:14:43 -0400640 BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
Chris Masonbb803952007-03-01 12:04:21 -0500641 return 0;
642
Chris Mason5f39d392007-10-15 16:14:19 -0400643 if (btrfs_header_nritems(mid) < 2)
Chris Mason54aa1f42007-06-22 14:16:25 -0400644 err_on_enospc = 1;
645
Chris Mason5f39d392007-10-15 16:14:19 -0400646 left = read_node_slot(root, parent, pslot - 1);
647 if (left) {
648 wret = btrfs_cow_block(trans, root, left,
649 parent, pslot - 1, &left);
Chris Mason54aa1f42007-06-22 14:16:25 -0400650 if (wret) {
651 ret = wret;
652 goto enospc;
653 }
Chris Mason2cc58cf2007-08-27 16:49:44 -0400654 }
Chris Mason5f39d392007-10-15 16:14:19 -0400655 right = read_node_slot(root, parent, pslot + 1);
656 if (right) {
657 wret = btrfs_cow_block(trans, root, right,
658 parent, pslot + 1, &right);
Chris Mason2cc58cf2007-08-27 16:49:44 -0400659 if (wret) {
660 ret = wret;
661 goto enospc;
662 }
663 }
664
665 /* first, try to make some room in the middle buffer */
Chris Mason5f39d392007-10-15 16:14:19 -0400666 if (left) {
667 orig_slot += btrfs_header_nritems(left);
668 wret = push_node_left(trans, root, left, mid);
Chris Mason79f95c82007-03-01 15:16:26 -0500669 if (wret < 0)
670 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -0400671 if (btrfs_header_nritems(mid) < 2)
Chris Mason54aa1f42007-06-22 14:16:25 -0400672 err_on_enospc = 1;
Chris Masonbb803952007-03-01 12:04:21 -0500673 }
Chris Mason79f95c82007-03-01 15:16:26 -0500674
675 /*
676 * then try to empty the right most buffer into the middle
677 */
Chris Mason5f39d392007-10-15 16:14:19 -0400678 if (right) {
679 wret = push_node_left(trans, root, mid, right);
Chris Mason54aa1f42007-06-22 14:16:25 -0400680 if (wret < 0 && wret != -ENOSPC)
Chris Mason79f95c82007-03-01 15:16:26 -0500681 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -0400682 if (btrfs_header_nritems(right) == 0) {
683 u64 blocknr = extent_buffer_blocknr(right);
684 clean_tree_block(trans, root, right);
685 wait_on_tree_block_writeback(root, right);
686 free_extent_buffer(right);
Chris Masonbb803952007-03-01 12:04:21 -0500687 right = NULL;
Chris Masone089f052007-03-16 16:20:31 -0400688 wret = del_ptr(trans, root, path, level + 1, pslot +
689 1);
Chris Masonbb803952007-03-01 12:04:21 -0500690 if (wret)
691 ret = wret;
Chris Masone089f052007-03-16 16:20:31 -0400692 wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
Chris Masonbb803952007-03-01 12:04:21 -0500693 if (wret)
694 ret = wret;
695 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400696 struct btrfs_disk_key right_key;
697 btrfs_node_key(right, &right_key, 0);
698 btrfs_set_node_key(parent, &right_key, pslot + 1);
699 btrfs_mark_buffer_dirty(parent);
Chris Masonbb803952007-03-01 12:04:21 -0500700 }
701 }
Chris Mason5f39d392007-10-15 16:14:19 -0400702 if (btrfs_header_nritems(mid) == 1) {
Chris Mason79f95c82007-03-01 15:16:26 -0500703 /*
704 * we're not allowed to leave a node with one item in the
705 * tree during a delete. A deletion from lower in the tree
706 * could try to delete the only pointer in this node.
707 * So, pull some keys from the left.
708 * There has to be a left pointer at this point because
709 * otherwise we would have pulled some pointers from the
710 * right
711 */
Chris Mason5f39d392007-10-15 16:14:19 -0400712 BUG_ON(!left);
713 wret = balance_node_right(trans, root, mid, left);
Chris Mason54aa1f42007-06-22 14:16:25 -0400714 if (wret < 0) {
Chris Mason79f95c82007-03-01 15:16:26 -0500715 ret = wret;
Chris Mason54aa1f42007-06-22 14:16:25 -0400716 goto enospc;
717 }
Chris Mason79f95c82007-03-01 15:16:26 -0500718 BUG_ON(wret == 1);
719 }
Chris Mason5f39d392007-10-15 16:14:19 -0400720 if (btrfs_header_nritems(mid) == 0) {
Chris Mason79f95c82007-03-01 15:16:26 -0500721 /* we've managed to empty the middle node, drop it */
Chris Mason5f39d392007-10-15 16:14:19 -0400722 u64 blocknr = extent_buffer_blocknr(mid);
723 clean_tree_block(trans, root, mid);
724 wait_on_tree_block_writeback(root, mid);
725 free_extent_buffer(mid);
Chris Masonbb803952007-03-01 12:04:21 -0500726 mid = NULL;
Chris Masone089f052007-03-16 16:20:31 -0400727 wret = del_ptr(trans, root, path, level + 1, pslot);
Chris Masonbb803952007-03-01 12:04:21 -0500728 if (wret)
729 ret = wret;
Chris Masone089f052007-03-16 16:20:31 -0400730 wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
Chris Masonbb803952007-03-01 12:04:21 -0500731 if (wret)
732 ret = wret;
Chris Mason79f95c82007-03-01 15:16:26 -0500733 } else {
734 /* update the parent key to reflect our changes */
Chris Mason5f39d392007-10-15 16:14:19 -0400735 struct btrfs_disk_key mid_key;
736 btrfs_node_key(mid, &mid_key, 0);
737 btrfs_set_node_key(parent, &mid_key, pslot);
738 btrfs_mark_buffer_dirty(parent);
Chris Mason79f95c82007-03-01 15:16:26 -0500739 }
Chris Masonbb803952007-03-01 12:04:21 -0500740
Chris Mason79f95c82007-03-01 15:16:26 -0500741 /* update the path */
Chris Mason5f39d392007-10-15 16:14:19 -0400742 if (left) {
743 if (btrfs_header_nritems(left) > orig_slot) {
744 extent_buffer_get(left);
745 path->nodes[level] = left;
Chris Masonbb803952007-03-01 12:04:21 -0500746 path->slots[level + 1] -= 1;
747 path->slots[level] = orig_slot;
Chris Mason5f39d392007-10-15 16:14:19 -0400748 if (mid)
749 free_extent_buffer(mid);
Chris Masonbb803952007-03-01 12:04:21 -0500750 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400751 orig_slot -= btrfs_header_nritems(left);
Chris Masonbb803952007-03-01 12:04:21 -0500752 path->slots[level] = orig_slot;
753 }
754 }
Chris Mason79f95c82007-03-01 15:16:26 -0500755 /* double check we haven't messed things up */
Chris Mason123abc82007-03-14 14:14:43 -0400756 check_block(root, path, level);
Chris Masone20d96d2007-03-22 12:13:20 -0400757 if (orig_ptr !=
Chris Mason5f39d392007-10-15 16:14:19 -0400758 btrfs_node_blockptr(path->nodes[level], path->slots[level]))
Chris Mason79f95c82007-03-01 15:16:26 -0500759 BUG();
Chris Mason54aa1f42007-06-22 14:16:25 -0400760enospc:
Chris Mason5f39d392007-10-15 16:14:19 -0400761 if (right)
762 free_extent_buffer(right);
763 if (left)
764 free_extent_buffer(left);
Chris Masonbb803952007-03-01 12:04:21 -0500765 return ret;
766}
767
Chris Masone66f7092007-04-20 13:16:02 -0400768/* returns zero if the push worked, non-zero otherwise */
769static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
770 struct btrfs_root *root,
771 struct btrfs_path *path, int level)
772{
Chris Mason5f39d392007-10-15 16:14:19 -0400773 struct extent_buffer *right = NULL;
774 struct extent_buffer *mid;
775 struct extent_buffer *left = NULL;
776 struct extent_buffer *parent = NULL;
Chris Masone66f7092007-04-20 13:16:02 -0400777 int ret = 0;
778 int wret;
779 int pslot;
780 int orig_slot = path->slots[level];
781 u64 orig_ptr;
782
783 if (level == 0)
784 return 1;
785
Chris Mason5f39d392007-10-15 16:14:19 -0400786 mid = path->nodes[level];
Chris Masone66f7092007-04-20 13:16:02 -0400787 orig_ptr = btrfs_node_blockptr(mid, orig_slot);
788
789 if (level < BTRFS_MAX_LEVEL - 1)
Chris Mason5f39d392007-10-15 16:14:19 -0400790 parent = path->nodes[level + 1];
Chris Masone66f7092007-04-20 13:16:02 -0400791 pslot = path->slots[level + 1];
792
Chris Mason5f39d392007-10-15 16:14:19 -0400793 if (!parent)
Chris Masone66f7092007-04-20 13:16:02 -0400794 return 1;
Chris Masone66f7092007-04-20 13:16:02 -0400795
Chris Mason5f39d392007-10-15 16:14:19 -0400796 left = read_node_slot(root, parent, pslot - 1);
Chris Masone66f7092007-04-20 13:16:02 -0400797
798 /* first, try to make some room in the middle buffer */
Chris Mason5f39d392007-10-15 16:14:19 -0400799 if (left) {
Chris Masone66f7092007-04-20 13:16:02 -0400800 u32 left_nr;
Chris Mason5f39d392007-10-15 16:14:19 -0400801 left_nr = btrfs_header_nritems(left);
Chris Mason33ade1f2007-04-20 13:48:57 -0400802 if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
803 wret = 1;
804 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400805 ret = btrfs_cow_block(trans, root, left, parent,
806 pslot - 1, &left);
Chris Mason54aa1f42007-06-22 14:16:25 -0400807 if (ret)
808 wret = 1;
809 else {
Chris Mason54aa1f42007-06-22 14:16:25 -0400810 wret = push_node_left(trans, root,
Chris Mason5f39d392007-10-15 16:14:19 -0400811 left, mid);
Chris Mason54aa1f42007-06-22 14:16:25 -0400812 }
Chris Mason33ade1f2007-04-20 13:48:57 -0400813 }
Chris Masone66f7092007-04-20 13:16:02 -0400814 if (wret < 0)
815 ret = wret;
816 if (wret == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -0400817 struct btrfs_disk_key disk_key;
Chris Masone66f7092007-04-20 13:16:02 -0400818 orig_slot += left_nr;
Chris Mason5f39d392007-10-15 16:14:19 -0400819 btrfs_node_key(mid, &disk_key, 0);
820 btrfs_set_node_key(parent, &disk_key, pslot);
821 btrfs_mark_buffer_dirty(parent);
822 if (btrfs_header_nritems(left) > orig_slot) {
823 path->nodes[level] = left;
Chris Masone66f7092007-04-20 13:16:02 -0400824 path->slots[level + 1] -= 1;
825 path->slots[level] = orig_slot;
Chris Mason5f39d392007-10-15 16:14:19 -0400826 free_extent_buffer(mid);
Chris Masone66f7092007-04-20 13:16:02 -0400827 } else {
828 orig_slot -=
Chris Mason5f39d392007-10-15 16:14:19 -0400829 btrfs_header_nritems(left);
Chris Masone66f7092007-04-20 13:16:02 -0400830 path->slots[level] = orig_slot;
Chris Mason5f39d392007-10-15 16:14:19 -0400831 free_extent_buffer(left);
Chris Masone66f7092007-04-20 13:16:02 -0400832 }
833 check_node(root, path, level);
834 return 0;
835 }
Chris Mason5f39d392007-10-15 16:14:19 -0400836 free_extent_buffer(left);
Chris Masone66f7092007-04-20 13:16:02 -0400837 }
Chris Mason5f39d392007-10-15 16:14:19 -0400838 right= read_node_slot(root, parent, pslot + 1);
Chris Masone66f7092007-04-20 13:16:02 -0400839
840 /*
841 * then try to empty the right most buffer into the middle
842 */
Chris Mason5f39d392007-10-15 16:14:19 -0400843 if (right) {
Chris Mason33ade1f2007-04-20 13:48:57 -0400844 u32 right_nr;
Chris Mason5f39d392007-10-15 16:14:19 -0400845 right_nr = btrfs_header_nritems(right);
Chris Mason33ade1f2007-04-20 13:48:57 -0400846 if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
847 wret = 1;
848 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400849 ret = btrfs_cow_block(trans, root, right,
850 parent, pslot + 1,
851 &right);
Chris Mason54aa1f42007-06-22 14:16:25 -0400852 if (ret)
853 wret = 1;
854 else {
Chris Mason54aa1f42007-06-22 14:16:25 -0400855 wret = balance_node_right(trans, root,
Chris Mason5f39d392007-10-15 16:14:19 -0400856 right, mid);
Chris Mason54aa1f42007-06-22 14:16:25 -0400857 }
Chris Mason33ade1f2007-04-20 13:48:57 -0400858 }
Chris Masone66f7092007-04-20 13:16:02 -0400859 if (wret < 0)
860 ret = wret;
861 if (wret == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -0400862 struct btrfs_disk_key disk_key;
863
864 btrfs_node_key(right, &disk_key, 0);
865 btrfs_set_node_key(parent, &disk_key, pslot + 1);
866 btrfs_mark_buffer_dirty(parent);
867
868 if (btrfs_header_nritems(mid) <= orig_slot) {
869 path->nodes[level] = right;
Chris Masone66f7092007-04-20 13:16:02 -0400870 path->slots[level + 1] += 1;
871 path->slots[level] = orig_slot -
Chris Mason5f39d392007-10-15 16:14:19 -0400872 btrfs_header_nritems(mid);
873 free_extent_buffer(mid);
Chris Masone66f7092007-04-20 13:16:02 -0400874 } else {
Chris Mason5f39d392007-10-15 16:14:19 -0400875 free_extent_buffer(right);
Chris Masone66f7092007-04-20 13:16:02 -0400876 }
877 check_node(root, path, level);
878 return 0;
879 }
Chris Mason5f39d392007-10-15 16:14:19 -0400880 free_extent_buffer(right);
Chris Masone66f7092007-04-20 13:16:02 -0400881 }
882 check_node(root, path, level);
883 return 1;
884}
885
Chris Mason74123bd2007-02-02 11:05:29 -0500886/*
Chris Mason3c69fae2007-08-07 15:52:22 -0400887 * readahead one full node of leaves
888 */
889static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
Chris Mason6702ed42007-08-07 16:15:09 -0400890 int level, int slot)
Chris Mason3c69fae2007-08-07 15:52:22 -0400891{
Chris Mason5f39d392007-10-15 16:14:19 -0400892 struct extent_buffer *node;
Chris Mason3c69fae2007-08-07 15:52:22 -0400893 int i;
894 u32 nritems;
Chris Mason3c69fae2007-08-07 15:52:22 -0400895 u64 blocknr;
896 u64 search;
897 u64 cluster_start;
898 int ret;
899 int nread = 0;
900 int direction = path->reada;
901 struct radix_tree_root found;
902 unsigned long gang[8];
Chris Mason5f39d392007-10-15 16:14:19 -0400903 struct extent_buffer *eb;
Chris Mason3c69fae2007-08-07 15:52:22 -0400904
Chris Mason6702ed42007-08-07 16:15:09 -0400905 if (level == 0)
Chris Mason3c69fae2007-08-07 15:52:22 -0400906 return;
907
Chris Mason6702ed42007-08-07 16:15:09 -0400908 if (!path->nodes[level])
909 return;
910
Chris Mason5f39d392007-10-15 16:14:19 -0400911 node = path->nodes[level];
Chris Mason3c69fae2007-08-07 15:52:22 -0400912 search = btrfs_node_blockptr(node, slot);
Chris Mason5f39d392007-10-15 16:14:19 -0400913 eb = btrfs_find_tree_block(root, search);
914 if (eb) {
915 free_extent_buffer(eb);
Chris Mason3c69fae2007-08-07 15:52:22 -0400916 return;
917 }
918
919 init_bit_radix(&found);
Chris Mason5f39d392007-10-15 16:14:19 -0400920 nritems = btrfs_header_nritems(node);
Chris Mason3c69fae2007-08-07 15:52:22 -0400921 for (i = slot; i < nritems; i++) {
Chris Mason3c69fae2007-08-07 15:52:22 -0400922 blocknr = btrfs_node_blockptr(node, i);
923 set_radix_bit(&found, blocknr);
924 }
925 if (direction > 0) {
926 cluster_start = search - 4;
927 if (cluster_start > search)
928 cluster_start = 0;
929 } else
930 cluster_start = search + 4;
931 while(1) {
932 ret = find_first_radix_bit(&found, gang, 0, ARRAY_SIZE(gang));
933 if (!ret)
934 break;
935 for (i = 0; i < ret; i++) {
936 blocknr = gang[i];
937 clear_radix_bit(&found, blocknr);
Chris Mason2cc58cf2007-08-27 16:49:44 -0400938 if (path->reada == 1 && nread > 16)
Chris Mason3c69fae2007-08-07 15:52:22 -0400939 continue;
Chris Masonf2183bd2007-08-10 14:42:37 -0400940 if (close_blocks(cluster_start, blocknr)) {
Chris Mason3c69fae2007-08-07 15:52:22 -0400941 readahead_tree_block(root, blocknr);
942 nread++;
Chris Mason3c69fae2007-08-07 15:52:22 -0400943 cluster_start = blocknr;
Chris Mason3c69fae2007-08-07 15:52:22 -0400944 }
945 }
946 }
947}
948/*
Chris Mason74123bd2007-02-02 11:05:29 -0500949 * look for key in the tree. path is filled in with nodes along the way
950 * if key is found, we return zero and you can find the item in the leaf
951 * level of the path (level 0)
952 *
953 * If the key isn't found, the path points to the slot where it should
Chris Masonaa5d6be2007-02-28 16:35:06 -0500954 * be inserted, and 1 is returned. If there are other errors during the
955 * search a negative error number is returned.
Chris Mason97571fd2007-02-24 13:39:08 -0500956 *
957 * if ins_len > 0, nodes and leaves will be split as we walk down the
958 * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if
959 * possible)
Chris Mason74123bd2007-02-02 11:05:29 -0500960 */
Chris Masone089f052007-03-16 16:20:31 -0400961int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
962 *root, struct btrfs_key *key, struct btrfs_path *p, int
963 ins_len, int cow)
Chris Masonbe0e5c02007-01-26 15:51:26 -0500964{
Chris Mason5f39d392007-10-15 16:14:19 -0400965 struct extent_buffer *b;
Chris Mason3c69fae2007-08-07 15:52:22 -0400966 u64 blocknr;
Chris Masonbe0e5c02007-01-26 15:51:26 -0500967 int slot;
968 int ret;
969 int level;
Chris Mason3c69fae2007-08-07 15:52:22 -0400970 int should_reada = p->reada;
Chris Mason9f3a7422007-08-07 15:52:19 -0400971 u8 lowest_level = 0;
972
Chris Mason6702ed42007-08-07 16:15:09 -0400973 lowest_level = p->lowest_level;
974 WARN_ON(lowest_level && ins_len);
Chris Mason22b0ebd2007-03-30 08:47:31 -0400975 WARN_ON(p->nodes[0] != NULL);
976 WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
Chris Masonbb803952007-03-01 12:04:21 -0500977again:
978 b = root->node;
Chris Mason5f39d392007-10-15 16:14:19 -0400979 extent_buffer_get(b);
Chris Masoneb60cea2007-02-02 09:18:22 -0500980 while (b) {
Chris Mason5f39d392007-10-15 16:14:19 -0400981 level = btrfs_header_level(b);
Chris Mason02217ed2007-03-02 16:08:05 -0500982 if (cow) {
983 int wret;
Chris Masone20d96d2007-03-22 12:13:20 -0400984 wret = btrfs_cow_block(trans, root, b,
985 p->nodes[level + 1],
986 p->slots[level + 1],
Yan252c38f2007-08-29 09:11:44 -0400987 &b);
Chris Mason54aa1f42007-06-22 14:16:25 -0400988 if (wret) {
Chris Mason5f39d392007-10-15 16:14:19 -0400989 free_extent_buffer(b);
Chris Mason54aa1f42007-06-22 14:16:25 -0400990 return wret;
991 }
Chris Mason02217ed2007-03-02 16:08:05 -0500992 }
993 BUG_ON(!cow && ins_len);
Chris Mason5f39d392007-10-15 16:14:19 -0400994 if (level != btrfs_header_level(b))
Chris Mason2c90e5d2007-04-02 10:50:19 -0400995 WARN_ON(1);
Chris Mason5f39d392007-10-15 16:14:19 -0400996 level = btrfs_header_level(b);
Chris Masoneb60cea2007-02-02 09:18:22 -0500997 p->nodes[level] = b;
Chris Mason123abc82007-03-14 14:14:43 -0400998 ret = check_block(root, p, level);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500999 if (ret)
1000 return -1;
Chris Mason5f39d392007-10-15 16:14:19 -04001001 ret = bin_search(b, key, level, &slot);
1002 if (level != 0) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001003 if (ret && slot > 0)
1004 slot -= 1;
1005 p->slots[level] = slot;
Chris Mason5f39d392007-10-15 16:14:19 -04001006 if (ins_len > 0 && btrfs_header_nritems(b) >=
Chris Masond4dbff92007-04-04 14:08:15 -04001007 BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
Chris Masone089f052007-03-16 16:20:31 -04001008 int sret = split_node(trans, root, p, level);
Chris Mason5c680ed2007-02-22 11:39:13 -05001009 BUG_ON(sret > 0);
1010 if (sret)
1011 return sret;
1012 b = p->nodes[level];
Chris Mason5c680ed2007-02-22 11:39:13 -05001013 slot = p->slots[level];
Chris Masonbb803952007-03-01 12:04:21 -05001014 } else if (ins_len < 0) {
Chris Masone089f052007-03-16 16:20:31 -04001015 int sret = balance_level(trans, root, p,
1016 level);
Chris Masonbb803952007-03-01 12:04:21 -05001017 if (sret)
1018 return sret;
1019 b = p->nodes[level];
Chris Masonf510cfe2007-10-15 16:14:48 -04001020 if (!b) {
1021 btrfs_release_path(NULL, p);
Chris Masonbb803952007-03-01 12:04:21 -05001022 goto again;
Chris Masonf510cfe2007-10-15 16:14:48 -04001023 }
Chris Masonbb803952007-03-01 12:04:21 -05001024 slot = p->slots[level];
Chris Mason5f39d392007-10-15 16:14:19 -04001025 BUG_ON(btrfs_header_nritems(b) == 1);
Chris Mason5c680ed2007-02-22 11:39:13 -05001026 }
Chris Mason9f3a7422007-08-07 15:52:19 -04001027 /* this is only true while dropping a snapshot */
1028 if (level == lowest_level)
1029 break;
Chris Mason5f39d392007-10-15 16:14:19 -04001030 blocknr = btrfs_node_blockptr(b, slot);
Chris Mason6702ed42007-08-07 16:15:09 -04001031 if (should_reada)
1032 reada_for_search(root, p, level, slot);
Chris Mason5f39d392007-10-15 16:14:19 -04001033 b = read_tree_block(root, btrfs_node_blockptr(b, slot));
Chris Masonbe0e5c02007-01-26 15:51:26 -05001034 } else {
1035 p->slots[level] = slot;
Chris Mason5f39d392007-10-15 16:14:19 -04001036 if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
Chris Mason0783fcf2007-03-12 20:12:07 -04001037 sizeof(struct btrfs_item) + ins_len) {
Chris Masond4dbff92007-04-04 14:08:15 -04001038 int sret = split_leaf(trans, root, key,
1039 p, ins_len);
Chris Mason5c680ed2007-02-22 11:39:13 -05001040 BUG_ON(sret > 0);
1041 if (sret)
1042 return sret;
1043 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05001044 return ret;
1045 }
1046 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001047 return 1;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001048}
1049
Chris Mason74123bd2007-02-02 11:05:29 -05001050/*
1051 * adjust the pointers going up the tree, starting at level
1052 * making sure the right key of each node is points to 'key'.
1053 * This is used after shifting pointers to the left, so it stops
1054 * fixing up pointers when a given leaf/node is not in slot 0 of the
1055 * higher levels
Chris Masonaa5d6be2007-02-28 16:35:06 -05001056 *
1057 * If this fails to write a tree block, it returns -1, but continues
1058 * fixing up the blocks in ram so the tree is consistent.
Chris Mason74123bd2007-02-02 11:05:29 -05001059 */
Chris Mason5f39d392007-10-15 16:14:19 -04001060static int fixup_low_keys(struct btrfs_trans_handle *trans,
1061 struct btrfs_root *root, struct btrfs_path *path,
1062 struct btrfs_disk_key *key, int level)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001063{
1064 int i;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001065 int ret = 0;
Chris Mason5f39d392007-10-15 16:14:19 -04001066 struct extent_buffer *t;
1067
Chris Mason234b63a2007-03-13 10:46:10 -04001068 for (i = level; i < BTRFS_MAX_LEVEL; i++) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001069 int tslot = path->slots[i];
Chris Masoneb60cea2007-02-02 09:18:22 -05001070 if (!path->nodes[i])
Chris Masonbe0e5c02007-01-26 15:51:26 -05001071 break;
Chris Mason5f39d392007-10-15 16:14:19 -04001072 t = path->nodes[i];
1073 btrfs_set_node_key(t, key, tslot);
Chris Masond6025572007-03-30 14:27:56 -04001074 btrfs_mark_buffer_dirty(path->nodes[i]);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001075 if (tslot != 0)
1076 break;
1077 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001078 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001079}
1080
Chris Mason74123bd2007-02-02 11:05:29 -05001081/*
1082 * try to push data from one node into the next node left in the
Chris Mason79f95c82007-03-01 15:16:26 -05001083 * tree.
Chris Masonaa5d6be2007-02-28 16:35:06 -05001084 *
1085 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
1086 * error, and > 0 if there was no room in the left hand block.
Chris Mason74123bd2007-02-02 11:05:29 -05001087 */
Chris Masone089f052007-03-16 16:20:31 -04001088static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Mason5f39d392007-10-15 16:14:19 -04001089 *root, struct extent_buffer *dst,
1090 struct extent_buffer *src)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001091{
Chris Masonbe0e5c02007-01-26 15:51:26 -05001092 int push_items = 0;
Chris Masonbb803952007-03-01 12:04:21 -05001093 int src_nritems;
1094 int dst_nritems;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001095 int ret = 0;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001096
Chris Mason5f39d392007-10-15 16:14:19 -04001097 src_nritems = btrfs_header_nritems(src);
1098 dst_nritems = btrfs_header_nritems(dst);
Chris Mason123abc82007-03-14 14:14:43 -04001099 push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
Chris Mason54aa1f42007-06-22 14:16:25 -04001100
Chris Masoneb60cea2007-02-02 09:18:22 -05001101 if (push_items <= 0) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05001102 return 1;
Chris Masoneb60cea2007-02-02 09:18:22 -05001103 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05001104
1105 if (src_nritems < push_items)
Chris Mason79f95c82007-03-01 15:16:26 -05001106 push_items = src_nritems;
1107
Chris Mason5f39d392007-10-15 16:14:19 -04001108 copy_extent_buffer(dst, src,
1109 btrfs_node_key_ptr_offset(dst_nritems),
1110 btrfs_node_key_ptr_offset(0),
1111 push_items * sizeof(struct btrfs_key_ptr));
1112
Chris Masonbb803952007-03-01 12:04:21 -05001113 if (push_items < src_nritems) {
Chris Mason5f39d392007-10-15 16:14:19 -04001114 memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
1115 btrfs_node_key_ptr_offset(push_items),
1116 (src_nritems - push_items) *
1117 sizeof(struct btrfs_key_ptr));
Chris Masonbb803952007-03-01 12:04:21 -05001118 }
Chris Mason5f39d392007-10-15 16:14:19 -04001119 btrfs_set_header_nritems(src, src_nritems - push_items);
1120 btrfs_set_header_nritems(dst, dst_nritems + push_items);
1121 btrfs_mark_buffer_dirty(src);
1122 btrfs_mark_buffer_dirty(dst);
Chris Masonbb803952007-03-01 12:04:21 -05001123 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001124}
1125
Chris Mason97571fd2007-02-24 13:39:08 -05001126/*
Chris Mason79f95c82007-03-01 15:16:26 -05001127 * try to push data from one node into the next node right in the
1128 * tree.
1129 *
1130 * returns 0 if some ptrs were pushed, < 0 if there was some horrible
1131 * error, and > 0 if there was no room in the right hand block.
1132 *
1133 * this will only push up to 1/2 the contents of the left node over
1134 */
Chris Mason5f39d392007-10-15 16:14:19 -04001135static int balance_node_right(struct btrfs_trans_handle *trans,
1136 struct btrfs_root *root,
1137 struct extent_buffer *dst,
1138 struct extent_buffer *src)
Chris Mason79f95c82007-03-01 15:16:26 -05001139{
Chris Mason79f95c82007-03-01 15:16:26 -05001140 int push_items = 0;
1141 int max_push;
1142 int src_nritems;
1143 int dst_nritems;
1144 int ret = 0;
Chris Mason79f95c82007-03-01 15:16:26 -05001145
Chris Mason5f39d392007-10-15 16:14:19 -04001146 src_nritems = btrfs_header_nritems(src);
1147 dst_nritems = btrfs_header_nritems(dst);
Chris Mason123abc82007-03-14 14:14:43 -04001148 push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
Chris Mason5f39d392007-10-15 16:14:19 -04001149 if (push_items <= 0)
Chris Mason79f95c82007-03-01 15:16:26 -05001150 return 1;
Chris Mason79f95c82007-03-01 15:16:26 -05001151
1152 max_push = src_nritems / 2 + 1;
1153 /* don't try to empty the node */
Yan252c38f2007-08-29 09:11:44 -04001154 if (max_push >= src_nritems)
Chris Mason79f95c82007-03-01 15:16:26 -05001155 return 1;
Yan252c38f2007-08-29 09:11:44 -04001156
Chris Mason79f95c82007-03-01 15:16:26 -05001157 if (max_push < push_items)
1158 push_items = max_push;
1159
Chris Mason5f39d392007-10-15 16:14:19 -04001160 memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items),
1161 btrfs_node_key_ptr_offset(0),
1162 (dst_nritems) *
1163 sizeof(struct btrfs_key_ptr));
Chris Masond6025572007-03-30 14:27:56 -04001164
Chris Mason5f39d392007-10-15 16:14:19 -04001165 copy_extent_buffer(dst, src,
1166 btrfs_node_key_ptr_offset(0),
1167 btrfs_node_key_ptr_offset(src_nritems - push_items),
1168 push_items * sizeof(struct btrfs_key_ptr));
Chris Mason79f95c82007-03-01 15:16:26 -05001169
Chris Mason5f39d392007-10-15 16:14:19 -04001170 btrfs_set_header_nritems(src, src_nritems - push_items);
1171 btrfs_set_header_nritems(dst, dst_nritems + push_items);
Chris Mason79f95c82007-03-01 15:16:26 -05001172
Chris Mason5f39d392007-10-15 16:14:19 -04001173 btrfs_mark_buffer_dirty(src);
1174 btrfs_mark_buffer_dirty(dst);
Chris Mason79f95c82007-03-01 15:16:26 -05001175 return ret;
1176}
1177
1178/*
Chris Mason97571fd2007-02-24 13:39:08 -05001179 * helper function to insert a new root level in the tree.
1180 * A new node is allocated, and a single item is inserted to
1181 * point to the existing root
Chris Masonaa5d6be2007-02-28 16:35:06 -05001182 *
1183 * returns zero on success or < 0 on failure.
Chris Mason97571fd2007-02-24 13:39:08 -05001184 */
Chris Mason5f39d392007-10-15 16:14:19 -04001185static int insert_new_root(struct btrfs_trans_handle *trans,
1186 struct btrfs_root *root,
1187 struct btrfs_path *path, int level)
Chris Mason5c680ed2007-02-22 11:39:13 -05001188{
Chris Mason5f39d392007-10-15 16:14:19 -04001189 struct extent_buffer *lower;
1190 struct extent_buffer *c;
1191 struct btrfs_disk_key lower_key;
Chris Mason5c680ed2007-02-22 11:39:13 -05001192
1193 BUG_ON(path->nodes[level]);
1194 BUG_ON(path->nodes[level-1] != root->node);
1195
Chris Mason5f39d392007-10-15 16:14:19 -04001196 c = btrfs_alloc_free_block(trans, root,
1197 extent_buffer_blocknr(root->node), 0);
1198 if (IS_ERR(c))
1199 return PTR_ERR(c);
1200 memset_extent_buffer(c, 0, 0, root->nodesize);
1201 btrfs_set_header_nritems(c, 1);
1202 btrfs_set_header_level(c, level);
1203 btrfs_set_header_blocknr(c, extent_buffer_blocknr(c));
1204 btrfs_set_header_generation(c, trans->transid);
1205 btrfs_set_header_owner(c, root->root_key.objectid);
1206 lower = path->nodes[level-1];
Chris Masond5719762007-03-23 10:01:08 -04001207
Chris Mason5f39d392007-10-15 16:14:19 -04001208 write_extent_buffer(c, root->fs_info->fsid,
1209 (unsigned long)btrfs_header_fsid(c),
1210 BTRFS_FSID_SIZE);
1211 if (level == 1)
1212 btrfs_item_key(lower, &lower_key, 0);
1213 else
1214 btrfs_node_key(lower, &lower_key, 0);
1215 btrfs_set_node_key(c, &lower_key, 0);
1216 btrfs_set_node_blockptr(c, 0, extent_buffer_blocknr(lower));
1217
1218 btrfs_mark_buffer_dirty(c);
Chris Masond5719762007-03-23 10:01:08 -04001219
Chris Mason5c680ed2007-02-22 11:39:13 -05001220 /* the super has an extra ref to root->node */
Chris Mason5f39d392007-10-15 16:14:19 -04001221 free_extent_buffer(root->node);
1222 root->node = c;
1223 extent_buffer_get(c);
1224 path->nodes[level] = c;
Chris Mason5c680ed2007-02-22 11:39:13 -05001225 path->slots[level] = 0;
1226 return 0;
1227}
1228
Chris Mason74123bd2007-02-02 11:05:29 -05001229/*
1230 * worker function to insert a single pointer in a node.
1231 * the node should have enough room for the pointer already
Chris Mason97571fd2007-02-24 13:39:08 -05001232 *
Chris Mason74123bd2007-02-02 11:05:29 -05001233 * slot and level indicate where you want the key to go, and
1234 * blocknr is the block the key points to.
Chris Masonaa5d6be2007-02-28 16:35:06 -05001235 *
1236 * returns zero on success and < 0 on any error
Chris Mason74123bd2007-02-02 11:05:29 -05001237 */
Chris Masone089f052007-03-16 16:20:31 -04001238static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
1239 *root, struct btrfs_path *path, struct btrfs_disk_key
1240 *key, u64 blocknr, int slot, int level)
Chris Mason74123bd2007-02-02 11:05:29 -05001241{
Chris Mason5f39d392007-10-15 16:14:19 -04001242 struct extent_buffer *lower;
Chris Mason74123bd2007-02-02 11:05:29 -05001243 int nritems;
Chris Mason5c680ed2007-02-22 11:39:13 -05001244
1245 BUG_ON(!path->nodes[level]);
Chris Mason5f39d392007-10-15 16:14:19 -04001246 lower = path->nodes[level];
1247 nritems = btrfs_header_nritems(lower);
Chris Mason74123bd2007-02-02 11:05:29 -05001248 if (slot > nritems)
1249 BUG();
Chris Mason123abc82007-03-14 14:14:43 -04001250 if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
Chris Mason74123bd2007-02-02 11:05:29 -05001251 BUG();
1252 if (slot != nritems) {
Chris Mason5f39d392007-10-15 16:14:19 -04001253 memmove_extent_buffer(lower,
1254 btrfs_node_key_ptr_offset(slot + 1),
1255 btrfs_node_key_ptr_offset(slot),
Chris Masond6025572007-03-30 14:27:56 -04001256 (nritems - slot) * sizeof(struct btrfs_key_ptr));
Chris Mason74123bd2007-02-02 11:05:29 -05001257 }
Chris Mason5f39d392007-10-15 16:14:19 -04001258 btrfs_set_node_key(lower, key, slot);
Chris Mason1d4f8a02007-03-13 09:28:32 -04001259 btrfs_set_node_blockptr(lower, slot, blocknr);
Chris Mason5f39d392007-10-15 16:14:19 -04001260 btrfs_set_header_nritems(lower, nritems + 1);
1261 btrfs_mark_buffer_dirty(lower);
Chris Mason098f59c2007-05-11 11:33:21 -04001262 check_node(root, path, level);
Chris Mason74123bd2007-02-02 11:05:29 -05001263 return 0;
1264}
1265
Chris Mason97571fd2007-02-24 13:39:08 -05001266/*
1267 * split the node at the specified level in path in two.
1268 * The path is corrected to point to the appropriate node after the split
1269 *
1270 * Before splitting this tries to make some room in the node by pushing
1271 * left and right, if either one works, it returns right away.
Chris Masonaa5d6be2007-02-28 16:35:06 -05001272 *
1273 * returns 0 on success and < 0 on failure
Chris Mason97571fd2007-02-24 13:39:08 -05001274 */
Chris Masone089f052007-03-16 16:20:31 -04001275static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
1276 *root, struct btrfs_path *path, int level)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001277{
Chris Mason5f39d392007-10-15 16:14:19 -04001278 struct extent_buffer *c;
1279 struct extent_buffer *split;
1280 struct btrfs_disk_key disk_key;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001281 int mid;
Chris Mason5c680ed2007-02-22 11:39:13 -05001282 int ret;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001283 int wret;
Chris Mason7518a232007-03-12 12:01:18 -04001284 u32 c_nritems;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001285
Chris Mason5f39d392007-10-15 16:14:19 -04001286 c = path->nodes[level];
1287 if (c == root->node) {
Chris Mason5c680ed2007-02-22 11:39:13 -05001288 /* trying to split the root, lets make a new one */
Chris Masone089f052007-03-16 16:20:31 -04001289 ret = insert_new_root(trans, root, path, level + 1);
Chris Mason5c680ed2007-02-22 11:39:13 -05001290 if (ret)
1291 return ret;
Chris Masone66f7092007-04-20 13:16:02 -04001292 } else {
1293 ret = push_nodes_for_insert(trans, root, path, level);
Chris Mason5f39d392007-10-15 16:14:19 -04001294 c = path->nodes[level];
1295 if (!ret && btrfs_header_nritems(c) <
Chris Masone66f7092007-04-20 13:16:02 -04001296 BTRFS_NODEPTRS_PER_BLOCK(root) - 1)
1297 return 0;
Chris Mason54aa1f42007-06-22 14:16:25 -04001298 if (ret < 0)
1299 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001300 }
Chris Masone66f7092007-04-20 13:16:02 -04001301
Chris Mason5f39d392007-10-15 16:14:19 -04001302 c_nritems = btrfs_header_nritems(c);
1303 split = btrfs_alloc_free_block(trans, root,
1304 extent_buffer_blocknr(c), 0);
1305 if (IS_ERR(split))
1306 return PTR_ERR(split);
Chris Mason54aa1f42007-06-22 14:16:25 -04001307
Chris Mason5f39d392007-10-15 16:14:19 -04001308 btrfs_set_header_flags(split, btrfs_header_flags(c));
1309 btrfs_set_header_level(split, btrfs_header_level(c));
1310 btrfs_set_header_blocknr(split, extent_buffer_blocknr(split));
1311 btrfs_set_header_generation(split, trans->transid);
1312 btrfs_set_header_owner(split, root->root_key.objectid);
1313 write_extent_buffer(split, root->fs_info->fsid,
1314 (unsigned long)btrfs_header_fsid(split),
1315 BTRFS_FSID_SIZE);
1316
Chris Mason7518a232007-03-12 12:01:18 -04001317 mid = (c_nritems + 1) / 2;
Chris Mason5f39d392007-10-15 16:14:19 -04001318
1319 copy_extent_buffer(split, c,
1320 btrfs_node_key_ptr_offset(0),
1321 btrfs_node_key_ptr_offset(mid),
1322 (c_nritems - mid) * sizeof(struct btrfs_key_ptr));
1323 btrfs_set_header_nritems(split, c_nritems - mid);
1324 btrfs_set_header_nritems(c, mid);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001325 ret = 0;
1326
Chris Mason5f39d392007-10-15 16:14:19 -04001327 btrfs_mark_buffer_dirty(c);
1328 btrfs_mark_buffer_dirty(split);
1329
1330 btrfs_node_key(split, &disk_key, 0);
1331 wret = insert_ptr(trans, root, path, &disk_key,
1332 extent_buffer_blocknr(split),
1333 path->slots[level + 1] + 1,
Chris Mason123abc82007-03-14 14:14:43 -04001334 level + 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001335 if (wret)
1336 ret = wret;
1337
Chris Mason5de08d72007-02-24 06:24:44 -05001338 if (path->slots[level] >= mid) {
Chris Mason5c680ed2007-02-22 11:39:13 -05001339 path->slots[level] -= mid;
Chris Mason5f39d392007-10-15 16:14:19 -04001340 free_extent_buffer(c);
1341 path->nodes[level] = split;
Chris Mason5c680ed2007-02-22 11:39:13 -05001342 path->slots[level + 1] += 1;
1343 } else {
Chris Mason5f39d392007-10-15 16:14:19 -04001344 free_extent_buffer(split);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001345 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05001346 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001347}
1348
Chris Mason74123bd2007-02-02 11:05:29 -05001349/*
1350 * how many bytes are required to store the items in a leaf. start
1351 * and nr indicate which items in the leaf to check. This totals up the
1352 * space used both by the item structs and the item data
1353 */
Chris Mason5f39d392007-10-15 16:14:19 -04001354static int leaf_space_used(struct extent_buffer *l, int start, int nr)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001355{
1356 int data_len;
Chris Mason5f39d392007-10-15 16:14:19 -04001357 int nritems = btrfs_header_nritems(l);
Chris Masond4dbff92007-04-04 14:08:15 -04001358 int end = min(nritems, start + nr) - 1;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001359
1360 if (!nr)
1361 return 0;
Chris Mason5f39d392007-10-15 16:14:19 -04001362 data_len = btrfs_item_end_nr(l, start);
1363 data_len = data_len - btrfs_item_offset_nr(l, end);
Chris Mason0783fcf2007-03-12 20:12:07 -04001364 data_len += sizeof(struct btrfs_item) * nr;
Chris Masond4dbff92007-04-04 14:08:15 -04001365 WARN_ON(data_len < 0);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001366 return data_len;
1367}
1368
Chris Mason74123bd2007-02-02 11:05:29 -05001369/*
Chris Masond4dbff92007-04-04 14:08:15 -04001370 * The space between the end of the leaf items and
1371 * the start of the leaf data. IOW, how much room
1372 * the leaf has left for both items and data
1373 */
Chris Mason5f39d392007-10-15 16:14:19 -04001374int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf)
Chris Masond4dbff92007-04-04 14:08:15 -04001375{
Chris Mason5f39d392007-10-15 16:14:19 -04001376 int nritems = btrfs_header_nritems(leaf);
1377 int ret;
1378 ret = BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
1379 if (ret < 0) {
1380 printk("leaf free space ret %d, leaf data size %lu, used %d nritems %d\n",
1381 ret, BTRFS_LEAF_DATA_SIZE(root),
1382 leaf_space_used(leaf, 0, nritems), nritems);
1383 }
1384 return ret;
Chris Masond4dbff92007-04-04 14:08:15 -04001385}
1386
1387/*
Chris Mason00ec4c52007-02-24 12:47:20 -05001388 * push some data in the path leaf to the right, trying to free up at
1389 * least data_size bytes. returns zero if the push worked, nonzero otherwise
Chris Masonaa5d6be2007-02-28 16:35:06 -05001390 *
1391 * returns 1 if the push failed because the other node didn't have enough
1392 * room, 0 if everything worked out and < 0 if there were major errors.
Chris Mason00ec4c52007-02-24 12:47:20 -05001393 */
Chris Masone089f052007-03-16 16:20:31 -04001394static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1395 *root, struct btrfs_path *path, int data_size)
Chris Mason00ec4c52007-02-24 12:47:20 -05001396{
Chris Mason5f39d392007-10-15 16:14:19 -04001397 struct extent_buffer *left = path->nodes[0];
1398 struct extent_buffer *right;
1399 struct extent_buffer *upper;
1400 struct btrfs_disk_key disk_key;
Chris Mason00ec4c52007-02-24 12:47:20 -05001401 int slot;
1402 int i;
1403 int free_space;
1404 int push_space = 0;
1405 int push_items = 0;
Chris Mason0783fcf2007-03-12 20:12:07 -04001406 struct btrfs_item *item;
Chris Mason7518a232007-03-12 12:01:18 -04001407 u32 left_nritems;
1408 u32 right_nritems;
Chris Mason5f39d392007-10-15 16:14:19 -04001409 u32 data_end;
Chris Mason54aa1f42007-06-22 14:16:25 -04001410 int ret;
Chris Mason00ec4c52007-02-24 12:47:20 -05001411
1412 slot = path->slots[1];
1413 if (!path->nodes[1]) {
1414 return 1;
1415 }
1416 upper = path->nodes[1];
Chris Mason5f39d392007-10-15 16:14:19 -04001417 if (slot >= btrfs_header_nritems(upper) - 1)
Chris Mason00ec4c52007-02-24 12:47:20 -05001418 return 1;
Chris Mason5f39d392007-10-15 16:14:19 -04001419
1420 right = read_tree_block(root, btrfs_node_blockptr(upper, slot + 1));
Chris Mason123abc82007-03-14 14:14:43 -04001421 free_space = btrfs_leaf_free_space(root, right);
Chris Mason0783fcf2007-03-12 20:12:07 -04001422 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason5f39d392007-10-15 16:14:19 -04001423 free_extent_buffer(right);
Chris Mason02217ed2007-03-02 16:08:05 -05001424 return 1;
1425 }
1426
Chris Mason5f39d392007-10-15 16:14:19 -04001427 /* cow and double check */
1428 ret = btrfs_cow_block(trans, root, right, upper,
1429 slot + 1, &right);
1430 if (ret) {
1431 free_extent_buffer(right);
Chris Masona429e512007-04-18 16:15:28 -04001432 return 1;
1433 }
Chris Mason5f39d392007-10-15 16:14:19 -04001434 free_space = btrfs_leaf_free_space(root, right);
1435 if (free_space < data_size + sizeof(struct btrfs_item)) {
1436 free_extent_buffer(right);
1437 return 1;
1438 }
1439
1440 left_nritems = btrfs_header_nritems(left);
1441 if (left_nritems == 0) {
1442 free_extent_buffer(right);
1443 return 1;
1444 }
1445
Chris Masona429e512007-04-18 16:15:28 -04001446 for (i = left_nritems - 1; i >= 1; i--) {
Chris Mason5f39d392007-10-15 16:14:19 -04001447 item = btrfs_item_nr(left, i);
Chris Mason00ec4c52007-02-24 12:47:20 -05001448 if (path->slots[0] == i)
1449 push_space += data_size + sizeof(*item);
Chris Mason5f39d392007-10-15 16:14:19 -04001450 if (btrfs_item_size(left, item) + sizeof(*item) + push_space >
Chris Mason0783fcf2007-03-12 20:12:07 -04001451 free_space)
Chris Mason00ec4c52007-02-24 12:47:20 -05001452 break;
1453 push_items++;
Chris Mason5f39d392007-10-15 16:14:19 -04001454 push_space += btrfs_item_size(left, item) + sizeof(*item);
Chris Mason00ec4c52007-02-24 12:47:20 -05001455 }
Chris Mason5f39d392007-10-15 16:14:19 -04001456
Chris Mason00ec4c52007-02-24 12:47:20 -05001457 if (push_items == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -04001458 free_extent_buffer(right);
Chris Mason00ec4c52007-02-24 12:47:20 -05001459 return 1;
1460 }
Chris Mason5f39d392007-10-15 16:14:19 -04001461
Chris Masona429e512007-04-18 16:15:28 -04001462 if (push_items == left_nritems)
1463 WARN_ON(1);
Chris Mason5f39d392007-10-15 16:14:19 -04001464
Chris Mason00ec4c52007-02-24 12:47:20 -05001465 /* push left to right */
Chris Mason5f39d392007-10-15 16:14:19 -04001466 right_nritems = btrfs_header_nritems(right);
1467 push_space = btrfs_item_end_nr(left, left_nritems - push_items);
Chris Mason123abc82007-03-14 14:14:43 -04001468 push_space -= leaf_data_end(root, left);
Chris Mason5f39d392007-10-15 16:14:19 -04001469
Chris Mason00ec4c52007-02-24 12:47:20 -05001470 /* make room in the right data area */
Chris Mason5f39d392007-10-15 16:14:19 -04001471 data_end = leaf_data_end(root, right);
1472 memmove_extent_buffer(right,
1473 btrfs_leaf_data(right) + data_end - push_space,
1474 btrfs_leaf_data(right) + data_end,
1475 BTRFS_LEAF_DATA_SIZE(root) - data_end);
1476
Chris Mason00ec4c52007-02-24 12:47:20 -05001477 /* copy from the left data area */
Chris Mason5f39d392007-10-15 16:14:19 -04001478 copy_extent_buffer(right, left, btrfs_leaf_data(right) +
Chris Masond6025572007-03-30 14:27:56 -04001479 BTRFS_LEAF_DATA_SIZE(root) - push_space,
1480 btrfs_leaf_data(left) + leaf_data_end(root, left),
1481 push_space);
Chris Mason5f39d392007-10-15 16:14:19 -04001482
1483 memmove_extent_buffer(right, btrfs_item_nr_offset(push_items),
1484 btrfs_item_nr_offset(0),
1485 right_nritems * sizeof(struct btrfs_item));
1486
Chris Mason00ec4c52007-02-24 12:47:20 -05001487 /* copy the items from left to right */
Chris Mason5f39d392007-10-15 16:14:19 -04001488 copy_extent_buffer(right, left, btrfs_item_nr_offset(0),
1489 btrfs_item_nr_offset(left_nritems - push_items),
1490 push_items * sizeof(struct btrfs_item));
Chris Mason00ec4c52007-02-24 12:47:20 -05001491
1492 /* update the item pointers */
Chris Mason7518a232007-03-12 12:01:18 -04001493 right_nritems += push_items;
Chris Mason5f39d392007-10-15 16:14:19 -04001494 btrfs_set_header_nritems(right, right_nritems);
Chris Mason123abc82007-03-14 14:14:43 -04001495 push_space = BTRFS_LEAF_DATA_SIZE(root);
Chris Mason7518a232007-03-12 12:01:18 -04001496 for (i = 0; i < right_nritems; i++) {
Chris Mason5f39d392007-10-15 16:14:19 -04001497 item = btrfs_item_nr(right, i);
1498 btrfs_set_item_offset(right, item, push_space -
1499 btrfs_item_size(right, item));
1500 push_space = btrfs_item_offset(right, item);
Chris Mason00ec4c52007-02-24 12:47:20 -05001501 }
Chris Mason7518a232007-03-12 12:01:18 -04001502 left_nritems -= push_items;
Chris Mason5f39d392007-10-15 16:14:19 -04001503 btrfs_set_header_nritems(left, left_nritems);
Chris Mason00ec4c52007-02-24 12:47:20 -05001504
Chris Mason5f39d392007-10-15 16:14:19 -04001505 btrfs_mark_buffer_dirty(left);
1506 btrfs_mark_buffer_dirty(right);
Chris Masona429e512007-04-18 16:15:28 -04001507
Chris Mason5f39d392007-10-15 16:14:19 -04001508 btrfs_item_key(right, &disk_key, 0);
1509 btrfs_set_node_key(upper, &disk_key, slot + 1);
Chris Masond6025572007-03-30 14:27:56 -04001510 btrfs_mark_buffer_dirty(upper);
Chris Mason02217ed2007-03-02 16:08:05 -05001511
Chris Mason00ec4c52007-02-24 12:47:20 -05001512 /* then fixup the leaf pointer in the path */
Chris Mason7518a232007-03-12 12:01:18 -04001513 if (path->slots[0] >= left_nritems) {
1514 path->slots[0] -= left_nritems;
Chris Mason5f39d392007-10-15 16:14:19 -04001515 free_extent_buffer(path->nodes[0]);
1516 path->nodes[0] = right;
Chris Mason00ec4c52007-02-24 12:47:20 -05001517 path->slots[1] += 1;
1518 } else {
Chris Mason5f39d392007-10-15 16:14:19 -04001519 free_extent_buffer(right);
Chris Mason00ec4c52007-02-24 12:47:20 -05001520 }
Chris Mason098f59c2007-05-11 11:33:21 -04001521 if (path->nodes[1])
1522 check_node(root, path, 1);
Chris Mason00ec4c52007-02-24 12:47:20 -05001523 return 0;
1524}
1525/*
Chris Mason74123bd2007-02-02 11:05:29 -05001526 * push some data in the path leaf to the left, trying to free up at
1527 * least data_size bytes. returns zero if the push worked, nonzero otherwise
1528 */
Chris Masone089f052007-03-16 16:20:31 -04001529static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1530 *root, struct btrfs_path *path, int data_size)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001531{
Chris Mason5f39d392007-10-15 16:14:19 -04001532 struct btrfs_disk_key disk_key;
1533 struct extent_buffer *right = path->nodes[0];
1534 struct extent_buffer *left;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001535 int slot;
1536 int i;
1537 int free_space;
1538 int push_space = 0;
1539 int push_items = 0;
Chris Mason0783fcf2007-03-12 20:12:07 -04001540 struct btrfs_item *item;
Chris Mason7518a232007-03-12 12:01:18 -04001541 u32 old_left_nritems;
Chris Mason5f39d392007-10-15 16:14:19 -04001542 u32 right_nritems;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001543 int ret = 0;
1544 int wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001545
1546 slot = path->slots[1];
Chris Mason5f39d392007-10-15 16:14:19 -04001547 if (slot == 0)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001548 return 1;
Chris Mason5f39d392007-10-15 16:14:19 -04001549 if (!path->nodes[1])
Chris Masonbe0e5c02007-01-26 15:51:26 -05001550 return 1;
Chris Mason5f39d392007-10-15 16:14:19 -04001551
1552 left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1],
1553 slot - 1));
Chris Mason123abc82007-03-14 14:14:43 -04001554 free_space = btrfs_leaf_free_space(root, left);
Chris Mason0783fcf2007-03-12 20:12:07 -04001555 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason5f39d392007-10-15 16:14:19 -04001556 free_extent_buffer(left);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001557 return 1;
1558 }
Chris Mason02217ed2007-03-02 16:08:05 -05001559
1560 /* cow and double check */
Chris Mason5f39d392007-10-15 16:14:19 -04001561 ret = btrfs_cow_block(trans, root, left,
1562 path->nodes[1], slot - 1, &left);
Chris Mason54aa1f42007-06-22 14:16:25 -04001563 if (ret) {
1564 /* we hit -ENOSPC, but it isn't fatal here */
Chris Mason5f39d392007-10-15 16:14:19 -04001565 free_extent_buffer(left);
Chris Mason54aa1f42007-06-22 14:16:25 -04001566 return 1;
1567 }
Chris Mason123abc82007-03-14 14:14:43 -04001568 free_space = btrfs_leaf_free_space(root, left);
Chris Mason0783fcf2007-03-12 20:12:07 -04001569 if (free_space < data_size + sizeof(struct btrfs_item)) {
Chris Mason5f39d392007-10-15 16:14:19 -04001570 free_extent_buffer(left);
Chris Mason02217ed2007-03-02 16:08:05 -05001571 return 1;
1572 }
1573
Chris Mason5f39d392007-10-15 16:14:19 -04001574 right_nritems = btrfs_header_nritems(right);
1575 if (right_nritems == 0) {
1576 free_extent_buffer(left);
Chris Masona429e512007-04-18 16:15:28 -04001577 return 1;
1578 }
1579
Chris Mason5f39d392007-10-15 16:14:19 -04001580 for (i = 0; i < right_nritems - 1; i++) {
1581 item = btrfs_item_nr(right, i);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001582 if (path->slots[0] == i)
1583 push_space += data_size + sizeof(*item);
Chris Mason5f39d392007-10-15 16:14:19 -04001584 if (btrfs_item_size(right, item) + sizeof(*item) + push_space >
Chris Mason0783fcf2007-03-12 20:12:07 -04001585 free_space)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001586 break;
1587 push_items++;
Chris Mason5f39d392007-10-15 16:14:19 -04001588 push_space += btrfs_item_size(right, item) + sizeof(*item);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001589 }
1590 if (push_items == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -04001591 free_extent_buffer(left);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001592 return 1;
1593 }
Chris Mason5f39d392007-10-15 16:14:19 -04001594 if (push_items == btrfs_header_nritems(right))
Chris Masona429e512007-04-18 16:15:28 -04001595 WARN_ON(1);
Chris Mason5f39d392007-10-15 16:14:19 -04001596
Chris Masonbe0e5c02007-01-26 15:51:26 -05001597 /* push data from right to left */
Chris Mason5f39d392007-10-15 16:14:19 -04001598 copy_extent_buffer(left, right,
1599 btrfs_item_nr_offset(btrfs_header_nritems(left)),
1600 btrfs_item_nr_offset(0),
1601 push_items * sizeof(struct btrfs_item));
1602
Chris Mason123abc82007-03-14 14:14:43 -04001603 push_space = BTRFS_LEAF_DATA_SIZE(root) -
Chris Mason5f39d392007-10-15 16:14:19 -04001604 btrfs_item_offset_nr(right, push_items -1);
1605
1606 copy_extent_buffer(left, right, btrfs_leaf_data(left) +
Chris Masond6025572007-03-30 14:27:56 -04001607 leaf_data_end(root, left) - push_space,
1608 btrfs_leaf_data(right) +
Chris Mason5f39d392007-10-15 16:14:19 -04001609 btrfs_item_offset_nr(right, push_items - 1),
Chris Masond6025572007-03-30 14:27:56 -04001610 push_space);
Chris Mason5f39d392007-10-15 16:14:19 -04001611 old_left_nritems = btrfs_header_nritems(left);
Chris Masoneb60cea2007-02-02 09:18:22 -05001612 BUG_ON(old_left_nritems < 0);
1613
Chris Mason0783fcf2007-03-12 20:12:07 -04001614 for (i = old_left_nritems; i < old_left_nritems + push_items; i++) {
Chris Mason5f39d392007-10-15 16:14:19 -04001615 u32 ioff;
1616 item = btrfs_item_nr(left, i);
1617 ioff = btrfs_item_offset(left, item);
1618 btrfs_set_item_offset(left, item,
1619 ioff - (BTRFS_LEAF_DATA_SIZE(root) -
1620 btrfs_item_offset_nr(left, old_left_nritems - 1)));
Chris Masonbe0e5c02007-01-26 15:51:26 -05001621 }
Chris Mason5f39d392007-10-15 16:14:19 -04001622 btrfs_set_header_nritems(left, old_left_nritems + push_items);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001623
1624 /* fixup right node */
Chris Mason5f39d392007-10-15 16:14:19 -04001625 push_space = btrfs_item_offset_nr(right, push_items - 1) -
1626 leaf_data_end(root, right);
1627 memmove_extent_buffer(right, btrfs_leaf_data(right) +
1628 BTRFS_LEAF_DATA_SIZE(root) - push_space,
1629 btrfs_leaf_data(right) +
1630 leaf_data_end(root, right), push_space);
1631
1632 memmove_extent_buffer(right, btrfs_item_nr_offset(0),
1633 btrfs_item_nr_offset(push_items),
1634 (btrfs_header_nritems(right) - push_items) *
1635 sizeof(struct btrfs_item));
1636
1637 right_nritems = btrfs_header_nritems(right) - push_items;
1638 btrfs_set_header_nritems(right, right_nritems);
Chris Mason123abc82007-03-14 14:14:43 -04001639 push_space = BTRFS_LEAF_DATA_SIZE(root);
Chris Masoneb60cea2007-02-02 09:18:22 -05001640
Chris Mason5f39d392007-10-15 16:14:19 -04001641 for (i = 0; i < right_nritems; i++) {
1642 item = btrfs_item_nr(right, i);
1643 btrfs_set_item_offset(right, item, push_space -
1644 btrfs_item_size(right, item));
1645 push_space = btrfs_item_offset(right, item);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001646 }
Chris Masoneb60cea2007-02-02 09:18:22 -05001647
Chris Mason5f39d392007-10-15 16:14:19 -04001648 btrfs_mark_buffer_dirty(left);
1649 btrfs_mark_buffer_dirty(right);
Chris Mason098f59c2007-05-11 11:33:21 -04001650
Chris Mason5f39d392007-10-15 16:14:19 -04001651 btrfs_item_key(right, &disk_key, 0);
1652 wret = fixup_low_keys(trans, root, path, &disk_key, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001653 if (wret)
1654 ret = wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001655
1656 /* then fixup the leaf pointer in the path */
1657 if (path->slots[0] < push_items) {
1658 path->slots[0] += old_left_nritems;
Chris Mason5f39d392007-10-15 16:14:19 -04001659 free_extent_buffer(path->nodes[0]);
1660 path->nodes[0] = left;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001661 path->slots[1] -= 1;
1662 } else {
Chris Mason5f39d392007-10-15 16:14:19 -04001663 free_extent_buffer(left);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001664 path->slots[0] -= push_items;
1665 }
Chris Masoneb60cea2007-02-02 09:18:22 -05001666 BUG_ON(path->slots[0] < 0);
Chris Mason098f59c2007-05-11 11:33:21 -04001667 if (path->nodes[1])
1668 check_node(root, path, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001669 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001670}
1671
Chris Mason74123bd2007-02-02 11:05:29 -05001672/*
1673 * split the path's leaf in two, making sure there is at least data_size
1674 * available for the resulting leaf level of the path.
Chris Masonaa5d6be2007-02-28 16:35:06 -05001675 *
1676 * returns 0 if all went well and < 0 on failure.
Chris Mason74123bd2007-02-02 11:05:29 -05001677 */
Chris Masone089f052007-03-16 16:20:31 -04001678static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
Chris Masond4dbff92007-04-04 14:08:15 -04001679 *root, struct btrfs_key *ins_key,
1680 struct btrfs_path *path, int data_size)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001681{
Chris Mason5f39d392007-10-15 16:14:19 -04001682 struct extent_buffer *l;
Chris Mason7518a232007-03-12 12:01:18 -04001683 u32 nritems;
Chris Masoneb60cea2007-02-02 09:18:22 -05001684 int mid;
1685 int slot;
Chris Mason5f39d392007-10-15 16:14:19 -04001686 struct extent_buffer *right;
Chris Mason0783fcf2007-03-12 20:12:07 -04001687 int space_needed = data_size + sizeof(struct btrfs_item);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001688 int data_copy_size;
1689 int rt_data_off;
1690 int i;
Chris Masond4dbff92007-04-04 14:08:15 -04001691 int ret = 0;
Chris Masonaa5d6be2007-02-28 16:35:06 -05001692 int wret;
Chris Masond4dbff92007-04-04 14:08:15 -04001693 int double_split = 0;
1694 struct btrfs_disk_key disk_key;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001695
Chris Mason40689472007-03-17 14:29:23 -04001696 /* first try to make some room by pushing left and right */
Chris Masone089f052007-03-16 16:20:31 -04001697 wret = push_leaf_left(trans, root, path, data_size);
Chris Masoneaee50e2007-03-13 11:17:52 -04001698 if (wret < 0)
1699 return wret;
1700 if (wret) {
Chris Masone089f052007-03-16 16:20:31 -04001701 wret = push_leaf_right(trans, root, path, data_size);
Chris Masoneaee50e2007-03-13 11:17:52 -04001702 if (wret < 0)
1703 return wret;
1704 }
Chris Mason5f39d392007-10-15 16:14:19 -04001705 l = path->nodes[0];
Chris Masonaa5d6be2007-02-28 16:35:06 -05001706
1707 /* did the pushes work? */
Chris Mason123abc82007-03-14 14:14:43 -04001708 if (btrfs_leaf_free_space(root, l) >=
1709 sizeof(struct btrfs_item) + data_size)
Chris Masonaa5d6be2007-02-28 16:35:06 -05001710 return 0;
1711
Chris Mason5c680ed2007-02-22 11:39:13 -05001712 if (!path->nodes[1]) {
Chris Masone089f052007-03-16 16:20:31 -04001713 ret = insert_new_root(trans, root, path, 1);
Chris Mason5c680ed2007-02-22 11:39:13 -05001714 if (ret)
1715 return ret;
1716 }
Chris Masoneb60cea2007-02-02 09:18:22 -05001717 slot = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04001718 nritems = btrfs_header_nritems(l);
Chris Masoneb60cea2007-02-02 09:18:22 -05001719 mid = (nritems + 1)/ 2;
Chris Mason54aa1f42007-06-22 14:16:25 -04001720
Chris Mason5f39d392007-10-15 16:14:19 -04001721 right = btrfs_alloc_free_block(trans, root,
1722 extent_buffer_blocknr(l), 0);
1723 if (IS_ERR(right))
1724 return PTR_ERR(right);
Chris Mason54aa1f42007-06-22 14:16:25 -04001725
Chris Mason5f39d392007-10-15 16:14:19 -04001726 memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header));
1727 btrfs_set_header_blocknr(right, extent_buffer_blocknr(right));
1728 btrfs_set_header_generation(right, trans->transid);
1729 btrfs_set_header_owner(right, root->root_key.objectid);
1730 btrfs_set_header_level(right, 0);
1731 write_extent_buffer(right, root->fs_info->fsid,
1732 (unsigned long)btrfs_header_fsid(right),
1733 BTRFS_FSID_SIZE);
1734
Chris Masond4dbff92007-04-04 14:08:15 -04001735 if (mid <= slot) {
1736 if (nritems == 1 ||
1737 leaf_space_used(l, mid, nritems - mid) + space_needed >
1738 BTRFS_LEAF_DATA_SIZE(root)) {
1739 if (slot >= nritems) {
1740 btrfs_cpu_key_to_disk(&disk_key, ins_key);
Chris Mason5f39d392007-10-15 16:14:19 -04001741 btrfs_set_header_nritems(right, 0);
Chris Masond4dbff92007-04-04 14:08:15 -04001742 wret = insert_ptr(trans, root, path,
1743 &disk_key,
Chris Mason5f39d392007-10-15 16:14:19 -04001744 extent_buffer_blocknr(right),
Chris Masond4dbff92007-04-04 14:08:15 -04001745 path->slots[1] + 1, 1);
1746 if (wret)
1747 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -04001748 free_extent_buffer(path->nodes[0]);
1749 path->nodes[0] = right;
Chris Masond4dbff92007-04-04 14:08:15 -04001750 path->slots[0] = 0;
1751 path->slots[1] += 1;
1752 return ret;
1753 }
1754 mid = slot;
1755 double_split = 1;
1756 }
1757 } else {
1758 if (leaf_space_used(l, 0, mid + 1) + space_needed >
1759 BTRFS_LEAF_DATA_SIZE(root)) {
1760 if (slot == 0) {
1761 btrfs_cpu_key_to_disk(&disk_key, ins_key);
Chris Mason5f39d392007-10-15 16:14:19 -04001762 btrfs_set_header_nritems(right, 0);
Chris Masond4dbff92007-04-04 14:08:15 -04001763 wret = insert_ptr(trans, root, path,
1764 &disk_key,
Chris Mason5f39d392007-10-15 16:14:19 -04001765 extent_buffer_blocknr(right),
Chris Mason098f59c2007-05-11 11:33:21 -04001766 path->slots[1], 1);
Chris Masond4dbff92007-04-04 14:08:15 -04001767 if (wret)
1768 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -04001769 free_extent_buffer(path->nodes[0]);
1770 path->nodes[0] = right;
Chris Masond4dbff92007-04-04 14:08:15 -04001771 path->slots[0] = 0;
Chris Masona429e512007-04-18 16:15:28 -04001772 if (path->slots[1] == 0) {
1773 wret = fixup_low_keys(trans, root,
1774 path, &disk_key, 1);
1775 if (wret)
1776 ret = wret;
1777 }
Chris Masond4dbff92007-04-04 14:08:15 -04001778 return ret;
1779 }
1780 mid = slot;
1781 double_split = 1;
1782 }
1783 }
Chris Mason5f39d392007-10-15 16:14:19 -04001784 nritems = nritems - mid;
1785 btrfs_set_header_nritems(right, nritems);
1786 data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(root, l);
1787
1788 copy_extent_buffer(right, l, btrfs_item_nr_offset(0),
1789 btrfs_item_nr_offset(mid),
1790 nritems * sizeof(struct btrfs_item));
1791
1792 copy_extent_buffer(right, l,
Chris Masond6025572007-03-30 14:27:56 -04001793 btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) -
1794 data_copy_size, btrfs_leaf_data(l) +
1795 leaf_data_end(root, l), data_copy_size);
Chris Mason74123bd2007-02-02 11:05:29 -05001796
Chris Mason5f39d392007-10-15 16:14:19 -04001797 rt_data_off = BTRFS_LEAF_DATA_SIZE(root) -
1798 btrfs_item_end_nr(l, mid);
1799
1800 for (i = 0; i < nritems; i++) {
1801 struct btrfs_item *item = btrfs_item_nr(right, i);
1802 u32 ioff = btrfs_item_offset(right, item);
1803 btrfs_set_item_offset(right, item, ioff + rt_data_off);
Chris Mason0783fcf2007-03-12 20:12:07 -04001804 }
Chris Mason74123bd2007-02-02 11:05:29 -05001805
Chris Mason5f39d392007-10-15 16:14:19 -04001806 btrfs_set_header_nritems(l, mid);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001807 ret = 0;
Chris Mason5f39d392007-10-15 16:14:19 -04001808 btrfs_item_key(right, &disk_key, 0);
1809 wret = insert_ptr(trans, root, path, &disk_key,
1810 extent_buffer_blocknr(right), path->slots[1] + 1, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05001811 if (wret)
1812 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -04001813
1814 btrfs_mark_buffer_dirty(right);
1815 btrfs_mark_buffer_dirty(l);
Chris Masoneb60cea2007-02-02 09:18:22 -05001816 BUG_ON(path->slots[0] != slot);
Chris Mason5f39d392007-10-15 16:14:19 -04001817
Chris Masonbe0e5c02007-01-26 15:51:26 -05001818 if (mid <= slot) {
Chris Mason5f39d392007-10-15 16:14:19 -04001819 free_extent_buffer(path->nodes[0]);
1820 path->nodes[0] = right;
Chris Masonbe0e5c02007-01-26 15:51:26 -05001821 path->slots[0] -= mid;
1822 path->slots[1] += 1;
Chris Masoneb60cea2007-02-02 09:18:22 -05001823 } else
Chris Mason5f39d392007-10-15 16:14:19 -04001824 free_extent_buffer(right);
1825
Chris Masoneb60cea2007-02-02 09:18:22 -05001826 BUG_ON(path->slots[0] < 0);
Chris Mason098f59c2007-05-11 11:33:21 -04001827 check_node(root, path, 1);
Chris Mason5f39d392007-10-15 16:14:19 -04001828 check_leaf(root, path, 0);
Chris Masond4dbff92007-04-04 14:08:15 -04001829
1830 if (!double_split)
1831 return ret;
Chris Mason54aa1f42007-06-22 14:16:25 -04001832
Chris Mason5f39d392007-10-15 16:14:19 -04001833 right = btrfs_alloc_free_block(trans, root,
1834 extent_buffer_blocknr(l), 0);
1835 if (IS_ERR(right))
1836 return PTR_ERR(right);
1837
1838 memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header));
1839 btrfs_set_header_blocknr(right, extent_buffer_blocknr(right));
1840 btrfs_set_header_generation(right, trans->transid);
1841 btrfs_set_header_owner(right, root->root_key.objectid);
1842 btrfs_set_header_level(right, 0);
1843 write_extent_buffer(right, root->fs_info->fsid,
1844 (unsigned long)btrfs_header_fsid(right),
1845 BTRFS_FSID_SIZE);
1846
Chris Masond4dbff92007-04-04 14:08:15 -04001847 btrfs_cpu_key_to_disk(&disk_key, ins_key);
Chris Mason5f39d392007-10-15 16:14:19 -04001848 btrfs_set_header_nritems(right, 0);
Chris Masond4dbff92007-04-04 14:08:15 -04001849 wret = insert_ptr(trans, root, path,
1850 &disk_key,
Chris Mason5f39d392007-10-15 16:14:19 -04001851 extent_buffer_blocknr(right),
Chris Masond4dbff92007-04-04 14:08:15 -04001852 path->slots[1], 1);
1853 if (wret)
1854 ret = wret;
Chris Masona429e512007-04-18 16:15:28 -04001855 if (path->slots[1] == 0) {
1856 wret = fixup_low_keys(trans, root, path, &disk_key, 1);
1857 if (wret)
1858 ret = wret;
1859 }
Chris Mason5f39d392007-10-15 16:14:19 -04001860 free_extent_buffer(path->nodes[0]);
1861 path->nodes[0] = right;
Chris Masond4dbff92007-04-04 14:08:15 -04001862 path->slots[0] = 0;
1863 check_node(root, path, 1);
1864 check_leaf(root, path, 0);
Chris Masonbe0e5c02007-01-26 15:51:26 -05001865 return ret;
1866}
1867
Chris Masonb18c6682007-04-17 13:26:50 -04001868int btrfs_truncate_item(struct btrfs_trans_handle *trans,
1869 struct btrfs_root *root,
1870 struct btrfs_path *path,
1871 u32 new_size)
1872{
1873 int ret = 0;
1874 int slot;
1875 int slot_orig;
Chris Mason5f39d392007-10-15 16:14:19 -04001876 struct extent_buffer *leaf;
1877 struct btrfs_item *item;
Chris Masonb18c6682007-04-17 13:26:50 -04001878 u32 nritems;
1879 unsigned int data_end;
1880 unsigned int old_data_start;
1881 unsigned int old_size;
1882 unsigned int size_diff;
1883 int i;
1884
1885 slot_orig = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04001886 leaf = path->nodes[0];
Chris Masonb18c6682007-04-17 13:26:50 -04001887
Chris Mason5f39d392007-10-15 16:14:19 -04001888 nritems = btrfs_header_nritems(leaf);
Chris Masonb18c6682007-04-17 13:26:50 -04001889 data_end = leaf_data_end(root, leaf);
1890
1891 slot = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04001892 old_data_start = btrfs_item_offset_nr(leaf, slot);
1893 old_size = btrfs_item_size_nr(leaf, slot);
Chris Masonb18c6682007-04-17 13:26:50 -04001894 BUG_ON(old_size <= new_size);
1895 size_diff = old_size - new_size;
1896
1897 BUG_ON(slot < 0);
1898 BUG_ON(slot >= nritems);
1899
1900 /*
1901 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1902 */
1903 /* first correct the data pointers */
1904 for (i = slot; i < nritems; i++) {
Chris Mason5f39d392007-10-15 16:14:19 -04001905 u32 ioff;
1906 item = btrfs_item_nr(leaf, i);
1907 ioff = btrfs_item_offset(leaf, item);
1908 btrfs_set_item_offset(leaf, item, ioff + size_diff);
Chris Masonb18c6682007-04-17 13:26:50 -04001909 }
1910 /* shift the data */
Chris Mason5f39d392007-10-15 16:14:19 -04001911 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
Chris Masonb18c6682007-04-17 13:26:50 -04001912 data_end + size_diff, btrfs_leaf_data(leaf) +
1913 data_end, old_data_start + new_size - data_end);
Chris Mason5f39d392007-10-15 16:14:19 -04001914
1915 item = btrfs_item_nr(leaf, slot);
1916 btrfs_set_item_size(leaf, item, new_size);
1917 btrfs_mark_buffer_dirty(leaf);
Chris Masonb18c6682007-04-17 13:26:50 -04001918
1919 ret = 0;
Chris Mason5f39d392007-10-15 16:14:19 -04001920 if (btrfs_leaf_free_space(root, leaf) < 0) {
1921 btrfs_print_leaf(root, leaf);
Chris Masonb18c6682007-04-17 13:26:50 -04001922 BUG();
Chris Mason5f39d392007-10-15 16:14:19 -04001923 }
Chris Masonb18c6682007-04-17 13:26:50 -04001924 check_leaf(root, path, 0);
1925 return ret;
1926}
1927
Chris Mason5f39d392007-10-15 16:14:19 -04001928int btrfs_extend_item(struct btrfs_trans_handle *trans,
1929 struct btrfs_root *root, struct btrfs_path *path,
1930 u32 data_size)
Chris Mason6567e832007-04-16 09:22:45 -04001931{
1932 int ret = 0;
1933 int slot;
1934 int slot_orig;
Chris Mason5f39d392007-10-15 16:14:19 -04001935 struct extent_buffer *leaf;
1936 struct btrfs_item *item;
Chris Mason6567e832007-04-16 09:22:45 -04001937 u32 nritems;
1938 unsigned int data_end;
1939 unsigned int old_data;
1940 unsigned int old_size;
1941 int i;
1942
1943 slot_orig = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04001944 leaf = path->nodes[0];
Chris Mason6567e832007-04-16 09:22:45 -04001945
Chris Mason5f39d392007-10-15 16:14:19 -04001946 nritems = btrfs_header_nritems(leaf);
Chris Mason6567e832007-04-16 09:22:45 -04001947 data_end = leaf_data_end(root, leaf);
1948
Chris Mason5f39d392007-10-15 16:14:19 -04001949 if (btrfs_leaf_free_space(root, leaf) < data_size) {
1950 btrfs_print_leaf(root, leaf);
Chris Mason6567e832007-04-16 09:22:45 -04001951 BUG();
Chris Mason5f39d392007-10-15 16:14:19 -04001952 }
Chris Mason6567e832007-04-16 09:22:45 -04001953 slot = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04001954 old_data = btrfs_item_end_nr(leaf, slot);
Chris Mason6567e832007-04-16 09:22:45 -04001955
1956 BUG_ON(slot < 0);
1957 BUG_ON(slot >= nritems);
1958
1959 /*
1960 * item0..itemN ... dataN.offset..dataN.size .. data0.size
1961 */
1962 /* first correct the data pointers */
1963 for (i = slot; i < nritems; i++) {
Chris Mason5f39d392007-10-15 16:14:19 -04001964 u32 ioff;
1965 item = btrfs_item_nr(leaf, i);
1966 ioff = btrfs_item_offset(leaf, item);
1967 btrfs_set_item_offset(leaf, item, ioff - data_size);
Chris Mason6567e832007-04-16 09:22:45 -04001968 }
Chris Mason5f39d392007-10-15 16:14:19 -04001969
Chris Mason6567e832007-04-16 09:22:45 -04001970 /* shift the data */
Chris Mason5f39d392007-10-15 16:14:19 -04001971 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
Chris Mason6567e832007-04-16 09:22:45 -04001972 data_end - data_size, btrfs_leaf_data(leaf) +
1973 data_end, old_data - data_end);
Chris Mason5f39d392007-10-15 16:14:19 -04001974
Chris Mason6567e832007-04-16 09:22:45 -04001975 data_end = old_data;
Chris Mason5f39d392007-10-15 16:14:19 -04001976 old_size = btrfs_item_size_nr(leaf, slot);
1977 item = btrfs_item_nr(leaf, slot);
1978 btrfs_set_item_size(leaf, item, old_size + data_size);
1979 btrfs_mark_buffer_dirty(leaf);
Chris Mason6567e832007-04-16 09:22:45 -04001980
1981 ret = 0;
Chris Mason5f39d392007-10-15 16:14:19 -04001982 if (btrfs_leaf_free_space(root, leaf) < 0) {
1983 btrfs_print_leaf(root, leaf);
Chris Mason6567e832007-04-16 09:22:45 -04001984 BUG();
Chris Mason5f39d392007-10-15 16:14:19 -04001985 }
Chris Mason6567e832007-04-16 09:22:45 -04001986 check_leaf(root, path, 0);
1987 return ret;
1988}
1989
Chris Mason74123bd2007-02-02 11:05:29 -05001990/*
1991 * Given a key and some data, insert an item into the tree.
1992 * This does all the path init required, making room in the tree if needed.
1993 */
Chris Mason5f39d392007-10-15 16:14:19 -04001994int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
1995 struct btrfs_root *root,
1996 struct btrfs_path *path,
1997 struct btrfs_key *cpu_key, u32 data_size)
Chris Masonbe0e5c02007-01-26 15:51:26 -05001998{
Chris Mason5f39d392007-10-15 16:14:19 -04001999 struct extent_buffer *leaf;
2000 struct btrfs_item *item;
Chris Masonaa5d6be2007-02-28 16:35:06 -05002001 int ret = 0;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002002 int slot;
Chris Masoneb60cea2007-02-02 09:18:22 -05002003 int slot_orig;
Chris Mason7518a232007-03-12 12:01:18 -04002004 u32 nritems;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002005 unsigned int data_end;
Chris Masone2fa7222007-03-12 16:22:34 -04002006 struct btrfs_disk_key disk_key;
2007
2008 btrfs_cpu_key_to_disk(&disk_key, cpu_key);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002009
Chris Mason74123bd2007-02-02 11:05:29 -05002010 /* create a root if there isn't one */
Chris Mason5c680ed2007-02-22 11:39:13 -05002011 if (!root->node)
Chris Masoncfaa7292007-02-21 17:04:57 -05002012 BUG();
Chris Mason5f39d392007-10-15 16:14:19 -04002013
Chris Masone089f052007-03-16 16:20:31 -04002014 ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
Chris Masoneb60cea2007-02-02 09:18:22 -05002015 if (ret == 0) {
Chris Masonf0930a32007-03-02 09:47:58 -05002016 return -EEXIST;
Chris Masonaa5d6be2007-02-28 16:35:06 -05002017 }
Chris Masoned2ff2c2007-03-01 18:59:40 -05002018 if (ret < 0)
2019 goto out;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002020
Chris Mason62e27492007-03-15 12:56:47 -04002021 slot_orig = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04002022 leaf = path->nodes[0];
Chris Mason74123bd2007-02-02 11:05:29 -05002023
Chris Mason5f39d392007-10-15 16:14:19 -04002024 nritems = btrfs_header_nritems(leaf);
Chris Mason123abc82007-03-14 14:14:43 -04002025 data_end = leaf_data_end(root, leaf);
Chris Masoneb60cea2007-02-02 09:18:22 -05002026
Chris Mason123abc82007-03-14 14:14:43 -04002027 if (btrfs_leaf_free_space(root, leaf) <
Chris Masond4dbff92007-04-04 14:08:15 -04002028 sizeof(struct btrfs_item) + data_size) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05002029 BUG();
Chris Masond4dbff92007-04-04 14:08:15 -04002030 }
Chris Mason5f39d392007-10-15 16:14:19 -04002031
Chris Mason62e27492007-03-15 12:56:47 -04002032 slot = path->slots[0];
Chris Masoneb60cea2007-02-02 09:18:22 -05002033 BUG_ON(slot < 0);
Chris Mason5f39d392007-10-15 16:14:19 -04002034
Chris Masonbe0e5c02007-01-26 15:51:26 -05002035 if (slot != nritems) {
2036 int i;
Chris Mason5f39d392007-10-15 16:14:19 -04002037 unsigned int old_data = btrfs_item_end_nr(leaf, slot);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002038
Chris Mason5f39d392007-10-15 16:14:19 -04002039 if (old_data < data_end) {
2040 btrfs_print_leaf(root, leaf);
2041 printk("slot %d old_data %d data_end %d\n",
2042 slot, old_data, data_end);
2043 BUG_ON(1);
2044 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05002045 /*
2046 * item0..itemN ... dataN.offset..dataN.size .. data0.size
2047 */
2048 /* first correct the data pointers */
Chris Mason0783fcf2007-03-12 20:12:07 -04002049 for (i = slot; i < nritems; i++) {
Chris Mason5f39d392007-10-15 16:14:19 -04002050 u32 ioff;
2051 item = btrfs_item_nr(leaf, i);
2052 ioff = btrfs_item_offset(leaf, item);
2053 btrfs_set_item_offset(leaf, item, ioff - data_size);
Chris Mason0783fcf2007-03-12 20:12:07 -04002054 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05002055
2056 /* shift the items */
Chris Mason5f39d392007-10-15 16:14:19 -04002057 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
2058 btrfs_item_nr_offset(slot),
Chris Masond6025572007-03-30 14:27:56 -04002059 (nritems - slot) * sizeof(struct btrfs_item));
Chris Masonbe0e5c02007-01-26 15:51:26 -05002060
2061 /* shift the data */
Chris Mason5f39d392007-10-15 16:14:19 -04002062 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
Chris Masond6025572007-03-30 14:27:56 -04002063 data_end - data_size, btrfs_leaf_data(leaf) +
2064 data_end, old_data - data_end);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002065 data_end = old_data;
2066 }
Chris Mason5f39d392007-10-15 16:14:19 -04002067
Chris Mason62e27492007-03-15 12:56:47 -04002068 /* setup the item for the new data */
Chris Mason5f39d392007-10-15 16:14:19 -04002069 btrfs_set_item_key(leaf, &disk_key, slot);
2070 item = btrfs_item_nr(leaf, slot);
2071 btrfs_set_item_offset(leaf, item, data_end - data_size);
2072 btrfs_set_item_size(leaf, item, data_size);
2073 btrfs_set_header_nritems(leaf, nritems + 1);
2074 btrfs_mark_buffer_dirty(leaf);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002075
2076 ret = 0;
Chris Mason8e19f2c2007-02-28 09:27:02 -05002077 if (slot == 0)
Chris Masone089f052007-03-16 16:20:31 -04002078 ret = fixup_low_keys(trans, root, path, &disk_key, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002079
Chris Mason5f39d392007-10-15 16:14:19 -04002080 if (btrfs_leaf_free_space(root, leaf) < 0) {
2081 btrfs_print_leaf(root, leaf);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002082 BUG();
Chris Mason5f39d392007-10-15 16:14:19 -04002083 }
Chris Mason62e27492007-03-15 12:56:47 -04002084 check_leaf(root, path, 0);
Chris Masoned2ff2c2007-03-01 18:59:40 -05002085out:
Chris Mason62e27492007-03-15 12:56:47 -04002086 return ret;
2087}
2088
2089/*
2090 * Given a key and some data, insert an item into the tree.
2091 * This does all the path init required, making room in the tree if needed.
2092 */
Chris Masone089f052007-03-16 16:20:31 -04002093int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
2094 *root, struct btrfs_key *cpu_key, void *data, u32
2095 data_size)
Chris Mason62e27492007-03-15 12:56:47 -04002096{
2097 int ret = 0;
Chris Mason2c90e5d2007-04-02 10:50:19 -04002098 struct btrfs_path *path;
Chris Mason5f39d392007-10-15 16:14:19 -04002099 struct extent_buffer *leaf;
2100 unsigned long ptr;
Chris Mason62e27492007-03-15 12:56:47 -04002101
Chris Mason2c90e5d2007-04-02 10:50:19 -04002102 path = btrfs_alloc_path();
2103 BUG_ON(!path);
Chris Mason2c90e5d2007-04-02 10:50:19 -04002104 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
Chris Mason62e27492007-03-15 12:56:47 -04002105 if (!ret) {
Chris Mason5f39d392007-10-15 16:14:19 -04002106 leaf = path->nodes[0];
2107 ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
2108 write_extent_buffer(leaf, data, ptr, data_size);
2109 btrfs_mark_buffer_dirty(leaf);
Chris Mason62e27492007-03-15 12:56:47 -04002110 }
Chris Mason2c90e5d2007-04-02 10:50:19 -04002111 btrfs_free_path(path);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002112 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002113}
2114
Chris Mason74123bd2007-02-02 11:05:29 -05002115/*
Chris Mason5de08d72007-02-24 06:24:44 -05002116 * delete the pointer from a given node.
Chris Mason74123bd2007-02-02 11:05:29 -05002117 *
2118 * If the delete empties a node, the node is removed from the tree,
2119 * continuing all the way the root if required. The root is converted into
2120 * a leaf if all the nodes are emptied.
2121 */
Chris Masone089f052007-03-16 16:20:31 -04002122static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
2123 struct btrfs_path *path, int level, int slot)
Chris Masonbe0e5c02007-01-26 15:51:26 -05002124{
Chris Mason5f39d392007-10-15 16:14:19 -04002125 struct extent_buffer *parent = path->nodes[level];
Chris Mason7518a232007-03-12 12:01:18 -04002126 u32 nritems;
Chris Masonaa5d6be2007-02-28 16:35:06 -05002127 int ret = 0;
Chris Masonbb803952007-03-01 12:04:21 -05002128 int wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002129
Chris Mason5f39d392007-10-15 16:14:19 -04002130 nritems = btrfs_header_nritems(parent);
Chris Masonbb803952007-03-01 12:04:21 -05002131 if (slot != nritems -1) {
Chris Mason5f39d392007-10-15 16:14:19 -04002132 memmove_extent_buffer(parent,
2133 btrfs_node_key_ptr_offset(slot),
2134 btrfs_node_key_ptr_offset(slot + 1),
Chris Masond6025572007-03-30 14:27:56 -04002135 sizeof(struct btrfs_key_ptr) *
2136 (nritems - slot - 1));
Chris Masonbb803952007-03-01 12:04:21 -05002137 }
Chris Mason7518a232007-03-12 12:01:18 -04002138 nritems--;
Chris Mason5f39d392007-10-15 16:14:19 -04002139 btrfs_set_header_nritems(parent, nritems);
Chris Mason7518a232007-03-12 12:01:18 -04002140 if (nritems == 0 && parent == root->node) {
Chris Mason5f39d392007-10-15 16:14:19 -04002141 BUG_ON(btrfs_header_level(root->node) != 1);
Chris Masonbb803952007-03-01 12:04:21 -05002142 /* just turn the root into a leaf and break */
Chris Mason5f39d392007-10-15 16:14:19 -04002143 btrfs_set_header_level(root->node, 0);
Chris Masonbb803952007-03-01 12:04:21 -05002144 } else if (slot == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -04002145 struct btrfs_disk_key disk_key;
2146
2147 btrfs_node_key(parent, &disk_key, 0);
2148 wret = fixup_low_keys(trans, root, path, &disk_key, level + 1);
Chris Mason0f70abe2007-02-28 16:46:22 -05002149 if (wret)
2150 ret = wret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002151 }
Chris Masond6025572007-03-30 14:27:56 -04002152 btrfs_mark_buffer_dirty(parent);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002153 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002154}
2155
Chris Mason74123bd2007-02-02 11:05:29 -05002156/*
2157 * delete the item at the leaf level in path. If that empties
2158 * the leaf, remove it from the tree
2159 */
Chris Masone089f052007-03-16 16:20:31 -04002160int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
2161 struct btrfs_path *path)
Chris Masonbe0e5c02007-01-26 15:51:26 -05002162{
Chris Masonbe0e5c02007-01-26 15:51:26 -05002163 int slot;
Chris Mason5f39d392007-10-15 16:14:19 -04002164 struct extent_buffer *leaf;
2165 struct btrfs_item *item;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002166 int doff;
2167 int dsize;
Chris Masonaa5d6be2007-02-28 16:35:06 -05002168 int ret = 0;
2169 int wret;
Chris Mason7518a232007-03-12 12:01:18 -04002170 u32 nritems;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002171
Chris Mason5f39d392007-10-15 16:14:19 -04002172 leaf = path->nodes[0];
Chris Mason4920c9a2007-01-26 16:38:42 -05002173 slot = path->slots[0];
Chris Mason5f39d392007-10-15 16:14:19 -04002174 doff = btrfs_item_offset_nr(leaf, slot);
2175 dsize = btrfs_item_size_nr(leaf, slot);
2176 nritems = btrfs_header_nritems(leaf);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002177
Chris Mason7518a232007-03-12 12:01:18 -04002178 if (slot != nritems - 1) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05002179 int i;
Chris Mason123abc82007-03-14 14:14:43 -04002180 int data_end = leaf_data_end(root, leaf);
Chris Mason5f39d392007-10-15 16:14:19 -04002181
2182 memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
Chris Masond6025572007-03-30 14:27:56 -04002183 data_end + dsize,
2184 btrfs_leaf_data(leaf) + data_end,
2185 doff - data_end);
Chris Mason5f39d392007-10-15 16:14:19 -04002186
Chris Mason0783fcf2007-03-12 20:12:07 -04002187 for (i = slot + 1; i < nritems; i++) {
Chris Mason5f39d392007-10-15 16:14:19 -04002188 u32 ioff;
2189 item = btrfs_item_nr(leaf, i);
2190 ioff = btrfs_item_offset(leaf, item);
2191 btrfs_set_item_offset(leaf, item, ioff + dsize);
Chris Mason0783fcf2007-03-12 20:12:07 -04002192 }
Chris Mason5f39d392007-10-15 16:14:19 -04002193 memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot),
2194 btrfs_item_nr_offset(slot + 1),
Chris Masond6025572007-03-30 14:27:56 -04002195 sizeof(struct btrfs_item) *
2196 (nritems - slot - 1));
Chris Masonbe0e5c02007-01-26 15:51:26 -05002197 }
Chris Mason5f39d392007-10-15 16:14:19 -04002198 btrfs_set_header_nritems(leaf, nritems - 1);
Chris Mason7518a232007-03-12 12:01:18 -04002199 nritems--;
Chris Mason5f39d392007-10-15 16:14:19 -04002200
Chris Mason74123bd2007-02-02 11:05:29 -05002201 /* delete the leaf if we've emptied it */
Chris Mason7518a232007-03-12 12:01:18 -04002202 if (nritems == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -04002203 if (leaf == root->node) {
2204 btrfs_set_header_level(leaf, 0);
Chris Mason9a8dd152007-02-23 08:38:36 -05002205 } else {
Chris Mason5f39d392007-10-15 16:14:19 -04002206 clean_tree_block(trans, root, leaf);
2207 wait_on_tree_block_writeback(root, leaf);
Chris Masone089f052007-03-16 16:20:31 -04002208 wret = del_ptr(trans, root, path, 1, path->slots[1]);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002209 if (wret)
2210 ret = wret;
Chris Masone089f052007-03-16 16:20:31 -04002211 wret = btrfs_free_extent(trans, root,
Chris Mason5f39d392007-10-15 16:14:19 -04002212 extent_buffer_blocknr(leaf),
2213 1, 1);
Chris Mason0f70abe2007-02-28 16:46:22 -05002214 if (wret)
2215 ret = wret;
Chris Mason9a8dd152007-02-23 08:38:36 -05002216 }
Chris Masonbe0e5c02007-01-26 15:51:26 -05002217 } else {
Chris Mason7518a232007-03-12 12:01:18 -04002218 int used = leaf_space_used(leaf, 0, nritems);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002219 if (slot == 0) {
Chris Mason5f39d392007-10-15 16:14:19 -04002220 struct btrfs_disk_key disk_key;
2221
2222 btrfs_item_key(leaf, &disk_key, 0);
Chris Masone089f052007-03-16 16:20:31 -04002223 wret = fixup_low_keys(trans, root, path,
Chris Mason5f39d392007-10-15 16:14:19 -04002224 &disk_key, 1);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002225 if (wret)
2226 ret = wret;
2227 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05002228
Chris Mason74123bd2007-02-02 11:05:29 -05002229 /* delete the leaf if it is mostly empty */
Chris Mason123abc82007-03-14 14:14:43 -04002230 if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
Chris Masonbe0e5c02007-01-26 15:51:26 -05002231 /* push_leaf_left fixes the path.
2232 * make sure the path still points to our leaf
2233 * for possible call to del_ptr below
2234 */
Chris Mason4920c9a2007-01-26 16:38:42 -05002235 slot = path->slots[1];
Chris Mason5f39d392007-10-15 16:14:19 -04002236 extent_buffer_get(leaf);
2237
Chris Masone089f052007-03-16 16:20:31 -04002238 wret = push_leaf_left(trans, root, path, 1);
Chris Mason54aa1f42007-06-22 14:16:25 -04002239 if (wret < 0 && wret != -ENOSPC)
Chris Masonaa5d6be2007-02-28 16:35:06 -05002240 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -04002241
2242 if (path->nodes[0] == leaf &&
2243 btrfs_header_nritems(leaf)) {
Chris Masone089f052007-03-16 16:20:31 -04002244 wret = push_leaf_right(trans, root, path, 1);
Chris Mason54aa1f42007-06-22 14:16:25 -04002245 if (wret < 0 && wret != -ENOSPC)
Chris Masonaa5d6be2007-02-28 16:35:06 -05002246 ret = wret;
2247 }
Chris Mason5f39d392007-10-15 16:14:19 -04002248
2249 if (btrfs_header_nritems(leaf) == 0) {
2250 u64 blocknr = extent_buffer_blocknr(leaf);
2251
2252 clean_tree_block(trans, root, leaf);
2253 wait_on_tree_block_writeback(root, leaf);
2254
Chris Masone089f052007-03-16 16:20:31 -04002255 wret = del_ptr(trans, root, path, 1, slot);
Chris Masonaa5d6be2007-02-28 16:35:06 -05002256 if (wret)
2257 ret = wret;
Chris Mason5f39d392007-10-15 16:14:19 -04002258
2259 free_extent_buffer(leaf);
Chris Masone089f052007-03-16 16:20:31 -04002260 wret = btrfs_free_extent(trans, root, blocknr,
2261 1, 1);
Chris Mason0f70abe2007-02-28 16:46:22 -05002262 if (wret)
2263 ret = wret;
Chris Mason5de08d72007-02-24 06:24:44 -05002264 } else {
Chris Mason5f39d392007-10-15 16:14:19 -04002265 btrfs_mark_buffer_dirty(leaf);
2266 free_extent_buffer(leaf);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002267 }
Chris Masond5719762007-03-23 10:01:08 -04002268 } else {
Chris Mason5f39d392007-10-15 16:14:19 -04002269 btrfs_mark_buffer_dirty(leaf);
Chris Masonbe0e5c02007-01-26 15:51:26 -05002270 }
2271 }
Chris Masonaa5d6be2007-02-28 16:35:06 -05002272 return ret;
Chris Masonbe0e5c02007-01-26 15:51:26 -05002273}
2274
Chris Mason97571fd2007-02-24 13:39:08 -05002275/*
2276 * walk up the tree as far as required to find the next leaf.
Chris Mason0f70abe2007-02-28 16:46:22 -05002277 * returns 0 if it found something or 1 if there are no greater leaves.
2278 * returns < 0 on io errors.
Chris Mason97571fd2007-02-24 13:39:08 -05002279 */
Chris Mason234b63a2007-03-13 10:46:10 -04002280int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
Chris Masond97e63b2007-02-20 16:40:44 -05002281{
2282 int slot;
2283 int level = 1;
2284 u64 blocknr;
Chris Mason5f39d392007-10-15 16:14:19 -04002285 struct extent_buffer *c;
2286 struct extent_buffer *next = NULL;
Chris Masond97e63b2007-02-20 16:40:44 -05002287
Chris Mason234b63a2007-03-13 10:46:10 -04002288 while(level < BTRFS_MAX_LEVEL) {
Chris Masond97e63b2007-02-20 16:40:44 -05002289 if (!path->nodes[level])
Chris Mason0f70abe2007-02-28 16:46:22 -05002290 return 1;
Chris Mason5f39d392007-10-15 16:14:19 -04002291
Chris Masond97e63b2007-02-20 16:40:44 -05002292 slot = path->slots[level] + 1;
2293 c = path->nodes[level];
Chris Mason5f39d392007-10-15 16:14:19 -04002294 if (slot >= btrfs_header_nritems(c)) {
Chris Masond97e63b2007-02-20 16:40:44 -05002295 level++;
2296 continue;
2297 }
Chris Mason5f39d392007-10-15 16:14:19 -04002298
2299 blocknr = btrfs_node_blockptr(c, slot);
Chris Masoncfaa7292007-02-21 17:04:57 -05002300 if (next)
Chris Mason5f39d392007-10-15 16:14:19 -04002301 free_extent_buffer(next);
2302
Chris Mason6702ed42007-08-07 16:15:09 -04002303 if (path->reada)
2304 reada_for_search(root, path, level, slot);
Chris Mason5f39d392007-10-15 16:14:19 -04002305
Chris Masond97e63b2007-02-20 16:40:44 -05002306 next = read_tree_block(root, blocknr);
2307 break;
2308 }
2309 path->slots[level] = slot;
2310 while(1) {
2311 level--;
2312 c = path->nodes[level];
Chris Mason5f39d392007-10-15 16:14:19 -04002313 free_extent_buffer(c);
Chris Masond97e63b2007-02-20 16:40:44 -05002314 path->nodes[level] = next;
2315 path->slots[level] = 0;
2316 if (!level)
2317 break;
Chris Mason6702ed42007-08-07 16:15:09 -04002318 if (path->reada)
Yan32020612007-08-27 15:17:54 -04002319 reada_for_search(root, path, level, 0);
Chris Mason5f39d392007-10-15 16:14:19 -04002320 next = read_tree_block(root, btrfs_node_blockptr(next, 0));
Chris Masond97e63b2007-02-20 16:40:44 -05002321 }
2322 return 0;
2323}