aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4a4f2d810d9f..a6969538bca2 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -365,8 +365,9 @@ error:
365 * 365 *
366 * returns 0 if everything worked, non-zero otherwise. 366 * returns 0 if everything worked, non-zero otherwise.
367 */ 367 */
368int alloc_extent(struct btrfs_root *root, u64 num_blocks, u64 search_start, 368static int alloc_extent(struct btrfs_root *root, u64 num_blocks,
369 u64 search_end, u64 owner, struct btrfs_key *ins) 369 u64 search_start, u64 search_end, u64 owner,
370 struct btrfs_key *ins)
370{ 371{
371 int ret; 372 int ret;
372 int pending_ret; 373 int pending_ret;
@@ -425,7 +426,12 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root)
425 return buf; 426 return buf;
426} 427}
427 428
428int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, int *level) 429/*
430 * helper function for drop_snapshot, this walks down the tree dropping ref
431 * counts as it goes.
432 */
433static int walk_down_tree(struct btrfs_root *root,
434 struct btrfs_path *path, int *level)
429{ 435{
430 struct btrfs_buffer *next; 436 struct btrfs_buffer *next;
431 struct btrfs_buffer *cur; 437 struct btrfs_buffer *cur;
@@ -437,6 +443,9 @@ int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, int *level)
437 BUG_ON(ret); 443 BUG_ON(ret);
438 if (refs > 1) 444 if (refs > 1)
439 goto out; 445 goto out;
446 /*
447 * walk down to the last node level and free all the leaves
448 */
440 while(*level > 0) { 449 while(*level > 0) {
441 cur = path->nodes[*level]; 450 cur = path->nodes[*level];
442 if (path->slots[*level] >= 451 if (path->slots[*level] >=
@@ -467,7 +476,13 @@ out:
467 return 0; 476 return 0;
468} 477}
469 478
470int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, int *level) 479/*
480 * helper for dropping snapshots. This walks back up the tree in the path
481 * to find the first node higher up where we haven't yet gone through
482 * all the slots
483 */
484static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path,
485 int *level)
471{ 486{
472 int i; 487 int i;
473 int slot; 488 int slot;
@@ -491,9 +506,15 @@ int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, int *level)
491 return 1; 506 return 1;
492} 507}
493 508
509/*
510 * drop the reference count on the tree rooted at 'snap'. This traverses
511 * the tree freeing any blocks that have a ref count of zero after being
512 * decremented.
513 */
494int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap) 514int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap)
495{ 515{
496 int ret; 516 int ret = 0;;
517 int wret;
497 int level; 518 int level;
498 struct btrfs_path path; 519 struct btrfs_path path;
499 int i; 520 int i;
@@ -506,18 +527,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap)
506 path.nodes[level] = snap; 527 path.nodes[level] = snap;
507 path.slots[level] = 0; 528 path.slots[level] = 0;
508 while(1) { 529 while(1) {
509 ret = walk_down_tree(root, &path, &level); 530 wret = walk_down_tree(root, &path, &level);
510 if (ret > 0) 531 if (wret > 0)
511 break; 532 break;
512 ret = walk_up_tree(root, &path, &level); 533 if (wret < 0)
513 if (ret > 0) 534 ret = wret;
535
536 wret = walk_up_tree(root, &path, &level);
537 if (wret > 0)
514 break; 538 break;
539 if (wret < 0)
540 ret = wret;
515 } 541 }
516 for (i = 0; i <= orig_level; i++) { 542 for (i = 0; i <= orig_level; i++) {
517 if (path.nodes[i]) { 543 if (path.nodes[i]) {
518 btrfs_block_release(root, path.nodes[i]); 544 btrfs_block_release(root, path.nodes[i]);
519 } 545 }
520 } 546 }
521 547 return ret;
522 return 0;
523} 548}