aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-02-16 13:57:04 -0500
committerChris Mason <chris.mason@oracle.com>2011-02-16 15:28:47 -0500
commitc87f08ca44e83b2c8d28f63f9c33f3a270a04bbe (patch)
tree05cebe37380861a89faaea50c1ccb360ffb0f975
parent91435650c233b93e0da389db74f4b2c11c5ad2d4 (diff)
Btrfs: allow balance to explicitly allocate chunks as it relocates
Btrfs device shrinking and balancing ends up reallocating all the blocks in order to allow COW to move them to new destinations. It is somewhat awkward in terms of ENOSPC because most of the enospc code is built around the idea that some operation on a reference counted tree triggers allocations in the non-reference counted trees. This commit changes the balancing code to deal with enospc by trying to allocate a new chunk. If that allocation succeeds, we go ahead and retry whatever failed due to enospc. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c7
-rw-r--r--fs/btrfs/relocation.c13
3 files changed, 21 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 6297701bc19c..28188a786da0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2219,6 +2219,8 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root,
2219 u64 start, u64 end); 2219 u64 start, u64 end);
2220int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, 2220int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
2221 u64 num_bytes); 2221 u64 num_bytes);
2222int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
2223 struct btrfs_root *root, u64 type);
2222 2224
2223/* ctree.c */ 2225/* ctree.c */
2224int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, 2226int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d375fc04a065..100e409e9053 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8066,6 +8066,13 @@ out:
8066 return ret; 8066 return ret;
8067} 8067}
8068 8068
8069int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
8070 struct btrfs_root *root, u64 type)
8071{
8072 u64 alloc_flags = get_alloc_profile(root, type);
8073 return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1);
8074}
8075
8069/* 8076/*
8070 * helper to account the unused space of all the readonly block group in the 8077 * helper to account the unused space of all the readonly block group in the
8071 * list. takes mirrors into account. 8078 * list. takes mirrors into account.
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 0825e4ed9447..31ade5802ae8 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -3654,6 +3654,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
3654 u32 item_size; 3654 u32 item_size;
3655 int ret; 3655 int ret;
3656 int err = 0; 3656 int err = 0;
3657 int progress = 0;
3657 3658
3658 path = btrfs_alloc_path(); 3659 path = btrfs_alloc_path();
3659 if (!path) 3660 if (!path)
@@ -3666,9 +3667,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
3666 } 3667 }
3667 3668
3668 while (1) { 3669 while (1) {
3670 progress++;
3669 trans = btrfs_start_transaction(rc->extent_root, 0); 3671 trans = btrfs_start_transaction(rc->extent_root, 0);
3670 BUG_ON(IS_ERR(trans)); 3672 BUG_ON(IS_ERR(trans));
3671 3673restart:
3672 if (update_backref_cache(trans, &rc->backref_cache)) { 3674 if (update_backref_cache(trans, &rc->backref_cache)) {
3673 btrfs_end_transaction(trans, rc->extent_root); 3675 btrfs_end_transaction(trans, rc->extent_root);
3674 continue; 3676 continue;
@@ -3781,6 +3783,15 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
3781 } 3783 }
3782 } 3784 }
3783 } 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 }
3784 3795
3785 btrfs_release_path(rc->extent_root, path); 3796 btrfs_release_path(rc->extent_root, path);
3786 clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, 3797 clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY,