summaryrefslogtreecommitdiff
path: root/check/mode-lowmem.c
diff options
context:
space:
mode:
authorSu Yue <suy.fnst@cn.fujitsu.com>2018-05-08 16:30:01 +0800
committerDavid Sterba <dsterba@suse.com>2018-06-07 16:37:30 +0200
commit4e320db9dd6885ad3f6264cf2595f0242d6893f8 (patch)
tree5dcf3e108cdc9b53eb4920660fd37fbe5b54d9ee /check/mode-lowmem.c
parente99f3775413cccf51ebf2d48e26cedc34226c293 (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/mode-lowmem.c')
-rw-r--r--check/mode-lowmem.c46
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