Btrfs: more inode indexed directory work
[linux-2.6-block.git] / fs / btrfs / extent-tree.c
1 #include <linux/module.h>
2 #include "ctree.h"
3 #include "disk-io.h"
4 #include "print-tree.h"
5 #include "transaction.h"
6
7 static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
8                             *orig_root, u64 num_blocks, u64 search_start, u64
9                             search_end, struct btrfs_key *ins);
10 static int finish_current_insert(struct btrfs_trans_handle *trans, struct
11                                  btrfs_root *extent_root);
12 static int del_pending_extents(struct btrfs_trans_handle *trans, struct
13                                btrfs_root *extent_root);
14
15 static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
16                          *root, u64 blocknr, u64 num_blocks)
17 {
18         struct btrfs_path *path;
19         int ret;
20         struct btrfs_key key;
21         struct btrfs_leaf *l;
22         struct btrfs_extent_item *item;
23         struct btrfs_key ins;
24         u32 refs;
25
26         find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1,
27                          &ins);
28         path = btrfs_alloc_path();
29         BUG_ON(!path);
30         btrfs_init_path(path);
31         key.objectid = blocknr;
32         key.flags = 0;
33         btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
34         key.offset = num_blocks;
35         ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
36                                 0, 1);
37         if (ret != 0)
38                 BUG();
39         BUG_ON(ret != 0);
40         l = btrfs_buffer_leaf(path->nodes[0]);
41         item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
42         refs = btrfs_extent_refs(item);
43         btrfs_set_extent_refs(item, refs + 1);
44         btrfs_mark_buffer_dirty(path->nodes[0]);
45
46         btrfs_release_path(root->fs_info->extent_root, path);
47         btrfs_free_path(path);
48         finish_current_insert(trans, root->fs_info->extent_root);
49         del_pending_extents(trans, root->fs_info->extent_root);
50         return 0;
51 }
52
53 static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
54                             *root, u64 blocknr, u64 num_blocks, u32 *refs)
55 {
56         struct btrfs_path *path;
57         int ret;
58         struct btrfs_key key;
59         struct btrfs_leaf *l;
60         struct btrfs_extent_item *item;
61
62         path = btrfs_alloc_path();
63         btrfs_init_path(path);
64         key.objectid = blocknr;
65         key.offset = num_blocks;
66         key.flags = 0;
67         btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
68         ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
69                                 0, 0);
70         if (ret != 0)
71                 BUG();
72         l = btrfs_buffer_leaf(path->nodes[0]);
73         item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
74         *refs = btrfs_extent_refs(item);
75         btrfs_release_path(root->fs_info->extent_root, path);
76         btrfs_free_path(path);
77         return 0;
78 }
79
80 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
81                   struct buffer_head *buf)
82 {
83         u64 blocknr;
84         struct btrfs_node *buf_node;
85         struct btrfs_leaf *buf_leaf;
86         struct btrfs_disk_key *key;
87         struct btrfs_file_extent_item *fi;
88         int i;
89         int leaf;
90         int ret;
91
92         if (!root->ref_cows)
93                 return 0;
94         buf_node = btrfs_buffer_node(buf);
95         leaf = btrfs_is_leaf(buf_node);
96         buf_leaf = btrfs_buffer_leaf(buf);
97         for (i = 0; i < btrfs_header_nritems(&buf_node->header); i++) {
98                 if (leaf) {
99                         key = &buf_leaf->items[i].key;
100                         if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY)
101                                 continue;
102                         fi = btrfs_item_ptr(buf_leaf, i,
103                                             struct btrfs_file_extent_item);
104                         ret = inc_block_ref(trans, root,
105                                     btrfs_file_extent_disk_blocknr(fi),
106                                     btrfs_file_extent_disk_num_blocks(fi));
107                         BUG_ON(ret);
108                 } else {
109                         blocknr = btrfs_node_blockptr(buf_node, i);
110                         ret = inc_block_ref(trans, root, blocknr, 1);
111                         BUG_ON(ret);
112                 }
113         }
114         return 0;
115 }
116
117 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
118                                btrfs_root *root)
119 {
120         unsigned long gang[8];
121         u64 first = 0;
122         int ret;
123         int i;
124         struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix;
125
126         while(1) {
127                 ret = find_first_radix_bit(pinned_radix, gang,
128                                            ARRAY_SIZE(gang));
129                 if (!ret)
130                         break;
131                 if (!first)
132                         first = gang[0];
133                 for (i = 0; i < ret; i++) {
134                         clear_radix_bit(pinned_radix, gang[i]);
135                 }
136         }
137         if (root->fs_info->last_insert.objectid > first)
138                 root->fs_info->last_insert.objectid = first;
139         root->fs_info->last_insert.offset = 0;
140         return 0;
141 }
142
143 static int finish_current_insert(struct btrfs_trans_handle *trans, struct
144                                  btrfs_root *extent_root)
145 {
146         struct btrfs_key ins;
147         struct btrfs_extent_item extent_item;
148         int i;
149         int ret;
150         u64 super_blocks_used;
151         struct btrfs_fs_info *info = extent_root->fs_info;
152
153         btrfs_set_extent_refs(&extent_item, 1);
154         btrfs_set_extent_owner(&extent_item,
155                 btrfs_header_parentid(btrfs_buffer_header(extent_root->node)));
156         ins.offset = 1;
157         ins.flags = 0;
158         btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
159
160         for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) {
161                 ins.objectid = extent_root->fs_info->current_insert.objectid +
162                                 i;
163                 super_blocks_used = btrfs_super_blocks_used(info->disk_super);
164                 btrfs_set_super_blocks_used(info->disk_super,
165                                             super_blocks_used + 1);
166                 ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
167                                         sizeof(extent_item));
168                 BUG_ON(ret);
169         }
170         extent_root->fs_info->current_insert.offset = 0;
171         return 0;
172 }
173
174 static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
175 {
176         int err;
177         struct btrfs_header *header;
178         struct buffer_head *bh;
179
180         if (!pending) {
181                 bh = btrfs_find_tree_block(root, blocknr);
182                 if (bh) {
183                         if (buffer_uptodate(bh)) {
184                                 u64 transid =
185                                     root->fs_info->running_transaction->transid;
186                                 header = btrfs_buffer_header(bh);
187                                 if (btrfs_header_generation(header) ==
188                                     transid) {
189                                         btrfs_block_release(root, bh);
190                                         return 0;
191                                 }
192                         }
193                         btrfs_block_release(root, bh);
194                 }
195                 err = set_radix_bit(&root->fs_info->pinned_radix, blocknr);
196         } else {
197                 err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr);
198         }
199         BUG_ON(err);
200         return 0;
201 }
202
203 /*
204  * remove an extent from the root, returns 0 on success
205  */
206 static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
207                          *root, u64 blocknr, u64 num_blocks, int pin)
208 {
209         struct btrfs_path *path;
210         struct btrfs_key key;
211         struct btrfs_fs_info *info = root->fs_info;
212         struct btrfs_root *extent_root = info->extent_root;
213         int ret;
214         struct btrfs_extent_item *ei;
215         struct btrfs_key ins;
216         u32 refs;
217
218         key.objectid = blocknr;
219         key.flags = 0;
220         btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
221         key.offset = num_blocks;
222
223         find_free_extent(trans, root, 0, 0, (u64)-1, &ins);
224         path = btrfs_alloc_path();
225         BUG_ON(!path);
226         btrfs_init_path(path);
227
228         ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
229         if (ret) {
230                 printk("failed to find %Lu\n", key.objectid);
231                 btrfs_print_tree(extent_root, extent_root->node);
232                 printk("failed to find %Lu\n", key.objectid);
233                 BUG();
234         }
235         ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
236                             struct btrfs_extent_item);
237         BUG_ON(ei->refs == 0);
238         refs = btrfs_extent_refs(ei) - 1;
239         btrfs_set_extent_refs(ei, refs);
240         btrfs_mark_buffer_dirty(path->nodes[0]);
241         if (refs == 0) {
242                 u64 super_blocks_used;
243
244                 if (pin) {
245                         ret = pin_down_block(root, blocknr, 0);
246                         BUG_ON(ret);
247                 }
248
249                 super_blocks_used = btrfs_super_blocks_used(info->disk_super);
250                 btrfs_set_super_blocks_used(info->disk_super,
251                                             super_blocks_used - num_blocks);
252                 ret = btrfs_del_item(trans, extent_root, path);
253                 if (ret)
254                         BUG();
255         }
256         btrfs_release_path(extent_root, path);
257         btrfs_free_path(path);
258         finish_current_insert(trans, extent_root);
259         return ret;
260 }
261
262 /*
263  * find all the blocks marked as pending in the radix tree and remove
264  * them from the extent map
265  */
266 static int del_pending_extents(struct btrfs_trans_handle *trans, struct
267                                btrfs_root *extent_root)
268 {
269         int ret;
270         int wret;
271         int err = 0;
272         unsigned long gang[4];
273         int i;
274         struct radix_tree_root *pending_radix;
275         struct radix_tree_root *pinned_radix;
276
277         pending_radix = &extent_root->fs_info->pending_del_radix;
278         pinned_radix = &extent_root->fs_info->pinned_radix;
279
280         while(1) {
281                 ret = find_first_radix_bit(pending_radix, gang,
282                                            ARRAY_SIZE(gang));
283                 if (!ret)
284                         break;
285                 for (i = 0; i < ret; i++) {
286                         wret = set_radix_bit(pinned_radix, gang[i]);
287                         BUG_ON(wret);
288                         wret = clear_radix_bit(pending_radix, gang[i]);
289                         BUG_ON(wret);
290                         wret = __free_extent(trans, extent_root,
291                                              gang[i], 1, 0);
292                         if (wret)
293                                 err = wret;
294                 }
295         }
296         return err;
297 }
298
299 /*
300  * remove an extent from the root, returns 0 on success
301  */
302 int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
303                       *root, u64 blocknr, u64 num_blocks, int pin)
304 {
305         struct btrfs_root *extent_root = root->fs_info->extent_root;
306         int pending_ret;
307         int ret;
308
309         if (root == extent_root) {
310                 pin_down_block(root, blocknr, 1);
311                 return 0;
312         }
313         ret = __free_extent(trans, root, blocknr, num_blocks, pin);
314         pending_ret = del_pending_extents(trans, root->fs_info->extent_root);
315         return ret ? ret : pending_ret;
316 }
317
318 /*
319  * walks the btree of allocated extents and find a hole of a given size.
320  * The key ins is changed to record the hole:
321  * ins->objectid == block start
322  * ins->flags = BTRFS_EXTENT_ITEM_KEY
323  * ins->offset == number of blocks
324  * Any available blocks before search_start are skipped.
325  */
326 static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
327                             *orig_root, u64 num_blocks, u64 search_start, u64
328                             search_end, struct btrfs_key *ins)
329 {
330         struct btrfs_path *path;
331         struct btrfs_key key;
332         int ret;
333         u64 hole_size = 0;
334         int slot = 0;
335         u64 last_block = 0;
336         u64 test_block;
337         int start_found;
338         struct btrfs_leaf *l;
339         struct btrfs_root * root = orig_root->fs_info->extent_root;
340         int total_needed = num_blocks;
341         int level;
342
343         path = btrfs_alloc_path();
344         ins->flags = 0;
345         btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
346
347         level = btrfs_header_level(btrfs_buffer_header(root->node));
348         total_needed += (level + 1) * 3;
349         if (root->fs_info->last_insert.objectid == 0 && search_end == (u64)-1) {
350                 struct btrfs_disk_key *last_key;
351                 btrfs_init_path(path);
352                 ins->objectid = (u64)-1;
353                 ins->offset = (u64)-1;
354                 ret = btrfs_search_slot(trans, root, ins, path, 0, 0);
355                 if (ret < 0)
356                         goto error;
357                 BUG_ON(ret == 0);
358                 if (path->slots[0] > 0)
359                         path->slots[0]--;
360                 l = btrfs_buffer_leaf(path->nodes[0]);
361                 last_key = &l->items[path->slots[0]].key;
362                 search_start = btrfs_disk_key_objectid(last_key);
363         }
364         if (root->fs_info->last_insert.objectid > search_start)
365                 search_start = root->fs_info->last_insert.objectid;
366
367 check_failed:
368         btrfs_init_path(path);
369         ins->objectid = search_start;
370         ins->offset = 0;
371         start_found = 0;
372         ret = btrfs_search_slot(trans, root, ins, path, 0, 0);
373         if (ret < 0)
374                 goto error;
375
376         if (path->slots[0] > 0)
377                 path->slots[0]--;
378
379         while (1) {
380                 l = btrfs_buffer_leaf(path->nodes[0]);
381                 slot = path->slots[0];
382                 if (slot >= btrfs_header_nritems(&l->header)) {
383                         ret = btrfs_next_leaf(root, path);
384                         if (ret == 0)
385                                 continue;
386                         if (ret < 0)
387                                 goto error;
388                         if (!start_found) {
389                                 ins->objectid = search_start;
390                                 ins->offset = (u64)-1;
391                                 start_found = 1;
392                                 goto check_pending;
393                         }
394                         ins->objectid = last_block > search_start ?
395                                         last_block : search_start;
396                         ins->offset = (u64)-1;
397                         goto check_pending;
398                 }
399                 btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
400                 if (key.objectid >= search_start) {
401                         if (start_found) {
402                                 if (last_block < search_start)
403                                         last_block = search_start;
404                                 hole_size = key.objectid - last_block;
405                                 if (hole_size > total_needed) {
406                                         ins->objectid = last_block;
407                                         ins->offset = hole_size;
408                                         goto check_pending;
409                                 }
410                         }
411                 }
412                 start_found = 1;
413                 last_block = key.objectid + key.offset;
414                 path->slots[0]++;
415         }
416         // FIXME -ENOSPC
417 check_pending:
418         /* we have to make sure we didn't find an extent that has already
419          * been allocated by the map tree or the original allocation
420          */
421         btrfs_release_path(root, path);
422         BUG_ON(ins->objectid < search_start);
423         for (test_block = ins->objectid;
424              test_block < ins->objectid + total_needed; test_block++) {
425                 if (test_radix_bit(&root->fs_info->pinned_radix,
426                                       test_block)) {
427                         search_start = test_block + 1;
428                         goto check_failed;
429                 }
430         }
431         BUG_ON(root->fs_info->current_insert.offset);
432         root->fs_info->current_insert.offset = total_needed - num_blocks;
433         root->fs_info->current_insert.objectid = ins->objectid + num_blocks;
434         root->fs_info->current_insert.flags = 0;
435         root->fs_info->last_insert.objectid = ins->objectid;
436         ins->offset = num_blocks;
437         btrfs_free_path(path);
438         return 0;
439 error:
440         btrfs_release_path(root, path);
441         btrfs_free_path(path);
442         return ret;
443 }
444
445 /*
446  * finds a free extent and does all the dirty work required for allocation
447  * returns the key for the extent through ins, and a tree buffer for
448  * the first block of the extent through buf.
449  *
450  * returns 0 if everything worked, non-zero otherwise.
451  */
452 int btrfs_alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
453                         *root, u64 num_blocks, u64 search_start, u64
454                         search_end, u64 owner, struct btrfs_key *ins)
455 {
456         int ret;
457         int pending_ret;
458         u64 super_blocks_used;
459         struct btrfs_fs_info *info = root->fs_info;
460         struct btrfs_root *extent_root = info->extent_root;
461         struct btrfs_extent_item extent_item;
462
463         btrfs_set_extent_refs(&extent_item, 1);
464         btrfs_set_extent_owner(&extent_item, owner);
465
466         if (root == extent_root) {
467                 BUG_ON(extent_root->fs_info->current_insert.offset == 0);
468                 BUG_ON(num_blocks != 1);
469                 BUG_ON(extent_root->fs_info->current_insert.flags ==
470                        extent_root->fs_info->current_insert.offset);
471                 ins->offset = 1;
472                 ins->objectid = extent_root->fs_info->current_insert.objectid +
473                                 extent_root->fs_info->current_insert.flags++;
474                 return 0;
475         }
476         ret = find_free_extent(trans, root, num_blocks, search_start,
477                                search_end, ins);
478         if (ret)
479                 return ret;
480
481         super_blocks_used = btrfs_super_blocks_used(info->disk_super);
482         btrfs_set_super_blocks_used(info->disk_super, super_blocks_used +
483                                     num_blocks);
484         ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
485                                 sizeof(extent_item));
486
487         finish_current_insert(trans, extent_root);
488         pending_ret = del_pending_extents(trans, extent_root);
489         if (ret)
490                 return ret;
491         if (pending_ret)
492                 return pending_ret;
493         return 0;
494 }
495
496 /*
497  * helper function to allocate a block for a given tree
498  * returns the tree buffer or NULL.
499  */
500 struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
501                                             struct btrfs_root *root)
502 {
503         struct btrfs_key ins;
504         int ret;
505         struct buffer_head *buf;
506
507         ret = btrfs_alloc_extent(trans, root, 1, 0, (unsigned long)-1,
508                 btrfs_header_parentid(btrfs_buffer_header(root->node)), &ins);
509         if (ret) {
510                 BUG();
511                 return NULL;
512         }
513         buf = btrfs_find_create_tree_block(root, ins.objectid);
514         set_buffer_uptodate(buf);
515         return buf;
516 }
517
518 static int drop_leaf_ref(struct btrfs_trans_handle *trans,
519                          struct btrfs_root *root, struct buffer_head *cur)
520 {
521         struct btrfs_disk_key *key;
522         struct btrfs_leaf *leaf;
523         struct btrfs_file_extent_item *fi;
524         int i;
525         int nritems;
526         int ret;
527
528         BUG_ON(!btrfs_is_leaf(btrfs_buffer_node(cur)));
529         leaf = btrfs_buffer_leaf(cur);
530         nritems = btrfs_header_nritems(&leaf->header);
531         for (i = 0; i < nritems; i++) {
532                 key = &leaf->items[i].key;
533                 if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY)
534                         continue;
535                 fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
536                 /*
537                  * FIXME make sure to insert a trans record that
538                  * repeats the snapshot del on crash
539                  */
540                 ret = btrfs_free_extent(trans, root,
541                                         btrfs_file_extent_disk_blocknr(fi),
542                                         btrfs_file_extent_disk_num_blocks(fi),
543                                         0);
544                 BUG_ON(ret);
545         }
546         return 0;
547 }
548
549 /*
550  * helper function for drop_snapshot, this walks down the tree dropping ref
551  * counts as it goes.
552  */
553 static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
554                           *root, struct btrfs_path *path, int *level)
555 {
556         struct buffer_head *next;
557         struct buffer_head *cur;
558         u64 blocknr;
559         int ret;
560         u32 refs;
561
562         WARN_ON(*level < 0);
563         WARN_ON(*level >= BTRFS_MAX_LEVEL);
564         ret = lookup_block_ref(trans, root, path->nodes[*level]->b_blocknr,
565                                1, &refs);
566         BUG_ON(ret);
567         if (refs > 1)
568                 goto out;
569         /*
570          * walk down to the last node level and free all the leaves
571          */
572         while(*level >= 0) {
573                 WARN_ON(*level < 0);
574                 WARN_ON(*level >= BTRFS_MAX_LEVEL);
575                 cur = path->nodes[*level];
576                 if (btrfs_header_level(btrfs_buffer_header(cur)) != *level)
577                         WARN_ON(1);
578                 if (path->slots[*level] >=
579                     btrfs_header_nritems(btrfs_buffer_header(cur)))
580                         break;
581                 if (*level == 0) {
582                         ret = drop_leaf_ref(trans, root, cur);
583                         BUG_ON(ret);
584                         break;
585                 }
586                 blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur),
587                                               path->slots[*level]);
588                 ret = lookup_block_ref(trans, root, blocknr, 1, &refs);
589                 BUG_ON(ret);
590                 if (refs != 1) {
591                         path->slots[*level]++;
592                         ret = btrfs_free_extent(trans, root, blocknr, 1, 1);
593                         BUG_ON(ret);
594                         continue;
595                 }
596                 next = read_tree_block(root, blocknr);
597                 WARN_ON(*level <= 0);
598                 if (path->nodes[*level-1])
599                         btrfs_block_release(root, path->nodes[*level-1]);
600                 path->nodes[*level-1] = next;
601                 *level = btrfs_header_level(btrfs_buffer_header(next));
602                 path->slots[*level] = 0;
603         }
604 out:
605         WARN_ON(*level < 0);
606         WARN_ON(*level >= BTRFS_MAX_LEVEL);
607         ret = btrfs_free_extent(trans, root,
608                                 path->nodes[*level]->b_blocknr, 1, 1);
609         btrfs_block_release(root, path->nodes[*level]);
610         path->nodes[*level] = NULL;
611         *level += 1;
612         BUG_ON(ret);
613         return 0;
614 }
615
616 /*
617  * helper for dropping snapshots.  This walks back up the tree in the path
618  * to find the first node higher up where we haven't yet gone through
619  * all the slots
620  */
621 static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
622                         *root, struct btrfs_path *path, int *level)
623 {
624         int i;
625         int slot;
626         int ret;
627         for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
628                 slot = path->slots[i];
629                 if (slot < btrfs_header_nritems(
630                     btrfs_buffer_header(path->nodes[i])) - 1) {
631                         path->slots[i]++;
632                         *level = i;
633                         return 0;
634                 } else {
635                         ret = btrfs_free_extent(trans, root,
636                                                 path->nodes[*level]->b_blocknr,
637                                                 1, 1);
638                         BUG_ON(ret);
639                         btrfs_block_release(root, path->nodes[*level]);
640                         path->nodes[*level] = NULL;
641                         *level = i + 1;
642                 }
643         }
644         return 1;
645 }
646
647 /*
648  * drop the reference count on the tree rooted at 'snap'.  This traverses
649  * the tree freeing any blocks that have a ref count of zero after being
650  * decremented.
651  */
652 int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
653                         *root, struct buffer_head *snap)
654 {
655         int ret = 0;
656         int wret;
657         int level;
658         struct btrfs_path *path;
659         int i;
660         int orig_level;
661
662         path = btrfs_alloc_path();
663         BUG_ON(!path);
664         btrfs_init_path(path);
665
666         level = btrfs_header_level(btrfs_buffer_header(snap));
667         orig_level = level;
668         path->nodes[level] = snap;
669         path->slots[level] = 0;
670         while(1) {
671                 wret = walk_down_tree(trans, root, path, &level);
672                 if (wret > 0)
673                         break;
674                 if (wret < 0)
675                         ret = wret;
676
677                 wret = walk_up_tree(trans, root, path, &level);
678                 if (wret > 0)
679                         break;
680                 if (wret < 0)
681                         ret = wret;
682         }
683         for (i = 0; i <= orig_level; i++) {
684                 if (path->nodes[i]) {
685                         btrfs_block_release(root, path->nodes[i]);
686                 }
687         }
688         btrfs_free_path(path);
689         return ret;
690 }