diff options
author | Su Yue <suy.fnst@cn.fujitsu.com> | 2018-05-08 16:30:01 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-06-07 16:37:30 +0200 |
commit | 4e320db9dd6885ad3f6264cf2595f0242d6893f8 (patch) | |
tree | 5dcf3e108cdc9b53eb4920660fd37fbe5b54d9ee /check | |
parent | e99f3775413cccf51ebf2d48e26cedc34226c293 (diff) |
btrfs-progs: check: lowmem: introduce avoid_extents_overwrite
Declare a global u64 variable last_allocated_chunk records start of
the last chunk allocated by lowmem repair.
Although global variable is not nice, it simplifies the code a lot.
avoid_extents_overwrite() prefers to allocate a new chunk first.
If it failed because of no space or wrong used bytes (like in
fsck-tests/004), then it tries to exclude metadata blocks which costs
a lot of time in large filesystems.
Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'check')
-rw-r--r-- | check/mode-lowmem.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index eb50c7e6..9ca533bd 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -28,6 +28,8 @@ #include "check/mode-common.h" #include "check/mode-lowmem.h" +static u64 last_allocated_chunk; + static int calc_extent_flag(struct btrfs_root *root, struct extent_buffer *eb, u64 *flags_ret) { @@ -491,6 +493,50 @@ static int try_to_force_cow_in_new_chunk(struct btrfs_fs_info *fs_info, return ret; } +static int avoid_extents_overwrite(struct btrfs_fs_info *fs_info) +{ + int ret; + int mixed = btrfs_fs_incompat(fs_info, MIXED_GROUPS); + + if (fs_info->excluded_extents) + return 0; + + if (last_allocated_chunk != (u64)-1) { + ret = try_to_force_cow_in_new_chunk(fs_info, + last_allocated_chunk, &last_allocated_chunk); + if (!ret) + goto out; + /* + * If failed, do not try to allocate chunk again in + * next call. + * If there is no space left to allocate, try to exclude all + * metadata blocks. Mixed filesystem is unsupported. + */ + last_allocated_chunk = (u64)-1; + if (ret != -ENOSPC || mixed) + goto out; + } + + printf( + "Try to exclude all metadata blcoks and extents, it may be slow\n"); + ret = exclude_metadata_blocks(fs_info); +out: + if (ret) + error("failed to avoid extents overwrite %s", strerror(-ret)); + return ret; +} + +static int end_avoid_extents_overwrite(struct btrfs_fs_info *fs_info) +{ + int ret = 0; + + cleanup_excluded_extents(fs_info); + if (last_allocated_chunk) + ret = clear_block_groups_full(fs_info, + BTRFS_BLOCK_GROUP_METADATA); + return ret; +} + /* * This function only handles BACKREF_MISSING, * If corresponding extent item exists, increase the ref, else insert an extent |