btrfs-progs: move space cache removal to rescue group

The option "--clear-space-cache" is not really that suitable for "btrfs
check" group, as there are some concerns:

- Allowing transid mismatch
- No leaf item checks

  Thoe behaviour are inherited from the default open ctree flags for
  "btrfs check", which can be unsafe if the end user just wants to clear
  the cache.

- Unclear if the cache clearing would happen along with repair

  Thankfully the clearing of space cache is done without any repair

Thus there is a proposal to move space cache removal to rescue group,
and this patch would do that exactly.

However this would lead to some behavior changes:

- Transid mismatch would be treated as error
- Leaf items size/offset would still be checked

  If we hit any above error, we should just abort without doing any
  write.

These change would increase the safety of the space cache removal, thus
I believe it's worthy to introduce such behavior change.

Since we're here, also add a small explanation on why we need this
dedicated tool to clear space cache (especially for v1 cache).

Issue: #698
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2023-10-24 19:53:57 +10:30 committed by David Sterba
parent f7fb93f1ac
commit 87b3197d81
5 changed files with 76 additions and 2 deletions

View file

@ -83,6 +83,10 @@ SAFE OR ADVISORY OPTIONS
See also the *clear_cache* mount option.
.. warning::
This option is deprecated, please use `btrfs rescue clear-space-cache`
instead, this option would be removed in the future eventually.
--clear-ino-cache
remove leftover items pertaining to the deprecated `inode cache` feature

View file

@ -56,6 +56,13 @@ clear-ino-cache <device>
The `inode cache` feature (enabled by mount option "inode_cache") has been
completely removed in 5.11 kernel.
clear-space-cache <v1|v2> <device>
Completely remove the on-disk data of free space cache of given version.
Especially for v1 free space cache, `clear_cache` mount option would only
remove the cache for updated block groups, the remaining would not be removed.
Thus this command is provided to manually clear the free space cache.
clear-uuid-tree <device>
Clear UUID tree, so that kernel can re-generate it at next read-write
mount.

View file

@ -28,7 +28,7 @@ _btrfs()
commands_balance='start pause cancel resume status'
commands_device='scan add delete remove ready stats usage'
commands_scrub='start cancel resume status'
commands_rescue='chunk-recover super-recover zero-log fix-device-size create-control-device clear-uuid-tree clear-ino-cache'
commands_rescue='chunk-recover super-recover zero-log fix-device-size create-control-device clear-uuid-tree clear-ino-cache clear-space-cache'
commands_inspect_internal='inode-resolve logical-resolve subvolid-resolve rootid min-dev-size dump-tree dump-super tree-stats map-swapfile'
commands_property='get set list'
commands_quota='enable disable rescan'

View file

@ -9965,7 +9965,6 @@ static const char * const cmd_check_usage[] = {
"Repair options:",
OPTLINE("--init-csum-tree", "create a new CRC tree"),
OPTLINE("--init-extent-tree", "create a new extent tree"),
OPTLINE("--clear-space-cache v1|v2", "clear space cache for v1 or v2"),
"",
"Check and reporting options:",
OPTLINE("--check-data-csum", "verify checksums of data blocks"),
@ -9975,6 +9974,7 @@ static const char * const cmd_check_usage[] = {
"",
"Deprecated or moved options:",
OPTLINE("--clear-ino-cache", "clear ino cache leftover items (moved to 'rescue' group)"),
OPTLINE("--clear-space-cache v1|v2", "clear space cache for v1 or v2 (moved to 'rescue' group)"),
NULL
};
@ -10234,6 +10234,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
}
if (clear_space_cache) {
warning("--clear-space-cache option is deprecated, please use \"btrfs rescue clear-space-cache\" instead");
ret = do_clear_free_space_cache(gfs_info, clear_space_cache);
err |= !!ret;
goto close_out;

View file

@ -456,6 +456,67 @@ out:
}
static DEFINE_SIMPLE_COMMAND(rescue_clear_ino_cache, "clear-ino-cache");
static const char * const cmd_rescue_clear_space_cache_usage[] = {
"btrfs rescue clear-space-cache (v1|v2) <device>",
"completely remove the v1 or v2 free space cache",
NULL
};
static int cmd_rescue_clear_space_cache(const struct cmd_struct *cmd,
int argc, char **argv)
{
struct open_ctree_args oca = { 0 };
struct btrfs_fs_info *fs_info;
char *devname;
char *version_string;
int clear_version;
int ret;
clean_args_no_options(cmd, argc, argv);
if (check_argc_exact(argc, 3))
return 1;
version_string = argv[optind];
devname = argv[optind + 1];
oca.filename = devname;
oca.flags = OPEN_CTREE_WRITES | OPEN_CTREE_EXCLUSIVE;
if (strncasecmp(version_string, "v1", strlen("v1")) == 0) {
clear_version = 1;
} else if (strncasecmp(version_string, "v2", strlen("v2")) == 0) {
clear_version = 2;
oca.flags |= OPEN_CTREE_INVALIDATE_FST;
} else {
error("invalid version string, has \"%s\" expect \"v1\" or \"v2\"",
version_string);
return 1;
}
ret = check_mounted(devname);
if (ret < 0) {
errno = -ret;
error("could not check mount status: %m");
return 1;
}
if (ret > 0) {
error("%s is currently mounted", devname);
return 1;
}
fs_info = open_ctree_fs_info(&oca);
if (!fs_info) {
error("cannot open file system");
return 1;
}
ret = do_clear_free_space_cache(fs_info, clear_version);
close_ctree(fs_info->tree_root);
if (ret < 0) {
errno = -ret;
error("failed to clear free space cache: %m");
}
return !!ret;
}
static DEFINE_SIMPLE_COMMAND(rescue_clear_space_cache, "clear-space-cache");
static const char rescue_cmd_group_info[] =
"toolbox for specific rescue operations";
@ -467,6 +528,7 @@ static const struct cmd_group rescue_cmd_group = {
&cmd_struct_rescue_fix_device_size,
&cmd_struct_rescue_create_control_device,
&cmd_struct_rescue_clear_ino_cache,
&cmd_struct_rescue_clear_space_cache,
&cmd_struct_rescue_clear_uuid_tree,
NULL
}