Commit db8fe64f authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: handle error in btrfs_cache_block_group

We have a BUG_ON(ret < 0) in find_free_extent from
btrfs_cache_block_group.  If we fail to allocate our ctl we'll just
panic, which is not good.  Instead just go on to another block group.
If we fail to find a block group we don't want to return ENOSPC, because
really we got a ENOMEM and that's the root of the problem.  Save our
return from btrfs_cache_block_group(), and then if we still fail to make
our allocation return that ret so we get the right error back.

Tested with inject-error.py from bcc.
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent f72ff01d
...@@ -3799,6 +3799,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, ...@@ -3799,6 +3799,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
u64 flags, int delalloc) u64 flags, int delalloc)
{ {
int ret = 0; int ret = 0;
int cache_block_group_error = 0;
struct btrfs_free_cluster *last_ptr = NULL; struct btrfs_free_cluster *last_ptr = NULL;
struct btrfs_block_group *block_group = NULL; struct btrfs_block_group *block_group = NULL;
struct find_free_extent_ctl ffe_ctl = {0}; struct find_free_extent_ctl ffe_ctl = {0};
...@@ -3958,7 +3959,20 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, ...@@ -3958,7 +3959,20 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
if (unlikely(!ffe_ctl.cached)) { if (unlikely(!ffe_ctl.cached)) {
ffe_ctl.have_caching_bg = true; ffe_ctl.have_caching_bg = true;
ret = btrfs_cache_block_group(block_group, 0); ret = btrfs_cache_block_group(block_group, 0);
BUG_ON(ret < 0);
/*
* If we get ENOMEM here or something else we want to
* try other block groups, because it may not be fatal.
* However if we can't find anything else we need to
* save our return here so that we return the actual
* error that caused problems, not ENOSPC.
*/
if (ret < 0) {
if (!cache_block_group_error)
cache_block_group_error = ret;
ret = 0;
goto loop;
}
ret = 0; ret = 0;
} }
...@@ -4045,7 +4059,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, ...@@ -4045,7 +4059,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
if (ret > 0) if (ret > 0)
goto search; goto search;
if (ret == -ENOSPC) { if (ret == -ENOSPC && !cache_block_group_error) {
/* /*
* Use ffe_ctl->total_free_space as fallback if we can't find * Use ffe_ctl->total_free_space as fallback if we can't find
* any contiguous hole. * any contiguous hole.
...@@ -4056,6 +4070,8 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, ...@@ -4056,6 +4070,8 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
space_info->max_extent_size = ffe_ctl.max_extent_size; space_info->max_extent_size = ffe_ctl.max_extent_size;
spin_unlock(&space_info->lock); spin_unlock(&space_info->lock);
ins->offset = ffe_ctl.max_extent_size; ins->offset = ffe_ctl.max_extent_size;
} else if (ret == -ENOSPC) {
ret = cache_block_group_error;
} }
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment