diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 045c9c2b2d7e..31ade5802ae8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1157,6 +1157,7 @@ static int clone_backref_node(struct btrfs_trans_handle *trans, | |||
1157 | new_node->bytenr = dest->node->start; | 1157 | new_node->bytenr = dest->node->start; |
1158 | new_node->level = node->level; | 1158 | new_node->level = node->level; |
1159 | new_node->lowest = node->lowest; | 1159 | new_node->lowest = node->lowest; |
1160 | new_node->checked = 1; | ||
1160 | new_node->root = dest; | 1161 | new_node->root = dest; |
1161 | 1162 | ||
1162 | if (!node->lowest) { | 1163 | if (!node->lowest) { |
@@ -2028,6 +2029,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
2028 | 2029 | ||
2029 | while (1) { | 2030 | while (1) { |
2030 | trans = btrfs_start_transaction(root, 0); | 2031 | trans = btrfs_start_transaction(root, 0); |
2032 | BUG_ON(IS_ERR(trans)); | ||
2031 | trans->block_rsv = rc->block_rsv; | 2033 | trans->block_rsv = rc->block_rsv; |
2032 | 2034 | ||
2033 | ret = btrfs_block_rsv_check(trans, root, rc->block_rsv, | 2035 | ret = btrfs_block_rsv_check(trans, root, rc->block_rsv, |
@@ -2147,6 +2149,12 @@ again: | |||
2147 | } | 2149 | } |
2148 | 2150 | ||
2149 | trans = btrfs_join_transaction(rc->extent_root, 1); | 2151 | trans = btrfs_join_transaction(rc->extent_root, 1); |
2152 | if (IS_ERR(trans)) { | ||
2153 | if (!err) | ||
2154 | btrfs_block_rsv_release(rc->extent_root, | ||
2155 | rc->block_rsv, num_bytes); | ||
2156 | return PTR_ERR(trans); | ||
2157 | } | ||
2150 | 2158 | ||
2151 | if (!err) { | 2159 | if (!err) { |
2152 | if (num_bytes != rc->merging_rsv_size) { | 2160 | if (num_bytes != rc->merging_rsv_size) { |
@@ -3222,6 +3230,7 @@ truncate: | |||
3222 | trans = btrfs_join_transaction(root, 0); | 3230 | trans = btrfs_join_transaction(root, 0); |
3223 | if (IS_ERR(trans)) { | 3231 | if (IS_ERR(trans)) { |
3224 | btrfs_free_path(path); | 3232 | btrfs_free_path(path); |
3233 | ret = PTR_ERR(trans); | ||
3225 | goto out; | 3234 | goto out; |
3226 | } | 3235 | } |
3227 | 3236 | ||
@@ -3628,6 +3637,7 @@ int prepare_to_relocate(struct reloc_control *rc) | |||
3628 | set_reloc_control(rc); | 3637 | set_reloc_control(rc); |
3629 | 3638 | ||
3630 | trans = btrfs_join_transaction(rc->extent_root, 1); | 3639 | trans = btrfs_join_transaction(rc->extent_root, 1); |
3640 | BUG_ON(IS_ERR(trans)); | ||
3631 | btrfs_commit_transaction(trans, rc->extent_root); | 3641 | btrfs_commit_transaction(trans, rc->extent_root); |
3632 | return 0; | 3642 | return 0; |
3633 | } | 3643 | } |
@@ -3644,6 +3654,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3644 | u32 item_size; | 3654 | u32 item_size; |
3645 | int ret; | 3655 | int ret; |
3646 | int err = 0; | 3656 | int err = 0; |
3657 | int progress = 0; | ||
3647 | 3658 | ||
3648 | path = btrfs_alloc_path(); | 3659 | path = btrfs_alloc_path(); |
3649 | if (!path) | 3660 | if (!path) |
@@ -3656,8 +3667,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3656 | } | 3667 | } |
3657 | 3668 | ||
3658 | while (1) { | 3669 | while (1) { |
3670 | progress++; | ||
3659 | trans = btrfs_start_transaction(rc->extent_root, 0); | 3671 | trans = btrfs_start_transaction(rc->extent_root, 0); |
3660 | 3672 | BUG_ON(IS_ERR(trans)); | |
3673 | restart: | ||
3661 | if (update_backref_cache(trans, &rc->backref_cache)) { | 3674 | if (update_backref_cache(trans, &rc->backref_cache)) { |
3662 | btrfs_end_transaction(trans, rc->extent_root); | 3675 | btrfs_end_transaction(trans, rc->extent_root); |
3663 | continue; | 3676 | continue; |
@@ -3770,6 +3783,15 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3770 | } | 3783 | } |
3771 | } | 3784 | } |
3772 | } | 3785 | } |
3786 | if (trans && progress && err == -ENOSPC) { | ||
3787 | ret = btrfs_force_chunk_alloc(trans, rc->extent_root, | ||
3788 | rc->block_group->flags); | ||
3789 | if (ret == 0) { | ||
3790 | err = 0; | ||
3791 | progress = 0; | ||
3792 | goto restart; | ||
3793 | } | ||
3794 | } | ||
3773 | 3795 | ||
3774 | btrfs_release_path(rc->extent_root, path); | 3796 | btrfs_release_path(rc->extent_root, path); |
3775 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, | 3797 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, |
@@ -3804,7 +3826,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3804 | 3826 | ||
3805 | /* get rid of pinned extents */ | 3827 | /* get rid of pinned extents */ |
3806 | trans = btrfs_join_transaction(rc->extent_root, 1); | 3828 | trans = btrfs_join_transaction(rc->extent_root, 1); |
3807 | btrfs_commit_transaction(trans, rc->extent_root); | 3829 | if (IS_ERR(trans)) |
3830 | err = PTR_ERR(trans); | ||
3831 | else | ||
3832 | btrfs_commit_transaction(trans, rc->extent_root); | ||
3808 | out_free: | 3833 | out_free: |
3809 | btrfs_free_block_rsv(rc->extent_root, rc->block_rsv); | 3834 | btrfs_free_block_rsv(rc->extent_root, rc->block_rsv); |
3810 | btrfs_free_path(path); | 3835 | btrfs_free_path(path); |
@@ -4022,6 +4047,7 @@ static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) | |||
4022 | int ret; | 4047 | int ret; |
4023 | 4048 | ||
4024 | trans = btrfs_start_transaction(root->fs_info->tree_root, 0); | 4049 | trans = btrfs_start_transaction(root->fs_info->tree_root, 0); |
4050 | BUG_ON(IS_ERR(trans)); | ||
4025 | 4051 | ||
4026 | memset(&root->root_item.drop_progress, 0, | 4052 | memset(&root->root_item.drop_progress, 0, |
4027 | sizeof(root->root_item.drop_progress)); | 4053 | sizeof(root->root_item.drop_progress)); |
@@ -4125,6 +4151,11 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4125 | set_reloc_control(rc); | 4151 | set_reloc_control(rc); |
4126 | 4152 | ||
4127 | trans = btrfs_join_transaction(rc->extent_root, 1); | 4153 | trans = btrfs_join_transaction(rc->extent_root, 1); |
4154 | if (IS_ERR(trans)) { | ||
4155 | unset_reloc_control(rc); | ||
4156 | err = PTR_ERR(trans); | ||
4157 | goto out_free; | ||
4158 | } | ||
4128 | 4159 | ||
4129 | rc->merge_reloc_tree = 1; | 4160 | rc->merge_reloc_tree = 1; |
4130 | 4161 | ||
@@ -4154,9 +4185,13 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4154 | unset_reloc_control(rc); | 4185 | unset_reloc_control(rc); |
4155 | 4186 | ||
4156 | trans = btrfs_join_transaction(rc->extent_root, 1); | 4187 | trans = btrfs_join_transaction(rc->extent_root, 1); |
4157 | btrfs_commit_transaction(trans, rc->extent_root); | 4188 | if (IS_ERR(trans)) |
4158 | out: | 4189 | err = PTR_ERR(trans); |
4190 | else | ||
4191 | btrfs_commit_transaction(trans, rc->extent_root); | ||
4192 | out_free: | ||
4159 | kfree(rc); | 4193 | kfree(rc); |
4194 | out: | ||
4160 | while (!list_empty(&reloc_roots)) { | 4195 | while (!list_empty(&reloc_roots)) { |
4161 | reloc_root = list_entry(reloc_roots.next, | 4196 | reloc_root = list_entry(reloc_roots.next, |
4162 | struct btrfs_root, root_list); | 4197 | struct btrfs_root, root_list); |