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>
This commit is contained in:
Родитель
91435650c2
Коммит
c87f08ca44
|
@ -2219,6 +2219,8 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root,
|
||||||
u64 start, u64 end);
|
u64 start, u64 end);
|
||||||
int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
|
int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
|
||||||
u64 num_bytes);
|
u64 num_bytes);
|
||||||
|
int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root, u64 type);
|
||||||
|
|
||||||
/* ctree.c */
|
/* ctree.c */
|
||||||
int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
|
int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
|
||||||
|
|
|
@ -8066,6 +8066,13 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root, u64 type)
|
||||||
|
{
|
||||||
|
u64 alloc_flags = get_alloc_profile(root, type);
|
||||||
|
return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* helper to account the unused space of all the readonly block group in the
|
* helper to account the unused space of all the readonly block group in the
|
||||||
* list. takes mirrors into account.
|
* list. takes mirrors into account.
|
||||||
|
|
|
@ -3654,6 +3654,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
|
||||||
u32 item_size;
|
u32 item_size;
|
||||||
int ret;
|
int ret;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
int progress = 0;
|
||||||
|
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
if (!path)
|
if (!path)
|
||||||
|
@ -3666,9 +3667,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
progress++;
|
||||||
trans = btrfs_start_transaction(rc->extent_root, 0);
|
trans = btrfs_start_transaction(rc->extent_root, 0);
|
||||||
BUG_ON(IS_ERR(trans));
|
BUG_ON(IS_ERR(trans));
|
||||||
|
restart:
|
||||||
if (update_backref_cache(trans, &rc->backref_cache)) {
|
if (update_backref_cache(trans, &rc->backref_cache)) {
|
||||||
btrfs_end_transaction(trans, rc->extent_root);
|
btrfs_end_transaction(trans, rc->extent_root);
|
||||||
continue;
|
continue;
|
||||||
|
@ -3781,6 +3783,15 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (trans && progress && err == -ENOSPC) {
|
||||||
|
ret = btrfs_force_chunk_alloc(trans, rc->extent_root,
|
||||||
|
rc->block_group->flags);
|
||||||
|
if (ret == 0) {
|
||||||
|
err = 0;
|
||||||
|
progress = 0;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
btrfs_release_path(rc->extent_root, path);
|
btrfs_release_path(rc->extent_root, path);
|
||||||
clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY,
|
clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче