diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 3be16ccc7eea..48a504260635 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -3203,6 +3203,7 @@ static int check_extent_flags(u64 flags) | |||
3203 | return 0; | 3203 | return 0; |
3204 | } | 3204 | } |
3205 | 3205 | ||
3206 | |||
3206 | static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | 3207 | static noinline_for_stack int relocate_block_group(struct reloc_control *rc) |
3207 | { | 3208 | { |
3208 | struct rb_root blocks = RB_ROOT; | 3209 | struct rb_root blocks = RB_ROOT; |
@@ -3220,6 +3221,9 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3220 | if (!path) | 3221 | if (!path) |
3221 | return -ENOMEM; | 3222 | return -ENOMEM; |
3222 | 3223 | ||
3224 | rc->extents_found = 0; | ||
3225 | rc->extents_skipped = 0; | ||
3226 | |||
3223 | rc->search_start = rc->block_group->key.objectid; | 3227 | rc->search_start = rc->block_group->key.objectid; |
3224 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, | 3228 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, |
3225 | GFP_NOFS); | 3229 | GFP_NOFS); |
@@ -3475,14 +3479,15 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
3475 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); | 3479 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); |
3476 | 3480 | ||
3477 | while (1) { | 3481 | while (1) { |
3478 | mutex_lock(&fs_info->cleaner_mutex); | ||
3479 | btrfs_clean_old_snapshots(fs_info->tree_root); | ||
3480 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3481 | |||
3482 | rc->extents_found = 0; | 3482 | rc->extents_found = 0; |
3483 | rc->extents_skipped = 0; | 3483 | rc->extents_skipped = 0; |
3484 | 3484 | ||
3485 | mutex_lock(&fs_info->cleaner_mutex); | ||
3486 | |||
3487 | btrfs_clean_old_snapshots(fs_info->tree_root); | ||
3485 | ret = relocate_block_group(rc); | 3488 | ret = relocate_block_group(rc); |
3489 | |||
3490 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3486 | if (ret < 0) { | 3491 | if (ret < 0) { |
3487 | err = ret; | 3492 | err = ret; |
3488 | break; | 3493 | break; |
@@ -3530,6 +3535,26 @@ out: | |||
3530 | return err; | 3535 | return err; |
3531 | } | 3536 | } |
3532 | 3537 | ||
3538 | static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) | ||
3539 | { | ||
3540 | struct btrfs_trans_handle *trans; | ||
3541 | int ret; | ||
3542 | |||
3543 | trans = btrfs_start_transaction(root->fs_info->tree_root, 1); | ||
3544 | |||
3545 | memset(&root->root_item.drop_progress, 0, | ||
3546 | sizeof(root->root_item.drop_progress)); | ||
3547 | root->root_item.drop_level = 0; | ||
3548 | btrfs_set_root_refs(&root->root_item, 0); | ||
3549 | ret = btrfs_update_root(trans, root->fs_info->tree_root, | ||
3550 | &root->root_key, &root->root_item); | ||
3551 | BUG_ON(ret); | ||
3552 | |||
3553 | ret = btrfs_end_transaction(trans, root->fs_info->tree_root); | ||
3554 | BUG_ON(ret); | ||
3555 | return 0; | ||
3556 | } | ||
3557 | |||
3533 | /* | 3558 | /* |
3534 | * recover relocation interrupted by system crash. | 3559 | * recover relocation interrupted by system crash. |
3535 | * | 3560 | * |
@@ -3589,8 +3614,12 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
3589 | fs_root = read_fs_root(root->fs_info, | 3614 | fs_root = read_fs_root(root->fs_info, |
3590 | reloc_root->root_key.offset); | 3615 | reloc_root->root_key.offset); |
3591 | if (IS_ERR(fs_root)) { | 3616 | if (IS_ERR(fs_root)) { |
3592 | err = PTR_ERR(fs_root); | 3617 | ret = PTR_ERR(fs_root); |
3593 | goto out; | 3618 | if (ret != -ENOENT) { |
3619 | err = ret; | ||
3620 | goto out; | ||
3621 | } | ||
3622 | mark_garbage_root(reloc_root); | ||
3594 | } | 3623 | } |
3595 | } | 3624 | } |
3596 | 3625 | ||