]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: introduce new "rescue=ignoresuperflags" mount option
authorQu Wenruo <wqu@suse.com>
Fri, 14 Jun 2024 04:22:31 +0000 (13:52 +0930)
committerDavid Sterba <dsterba@suse.com>
Thu, 11 Jul 2024 13:33:30 +0000 (15:33 +0200)
This new mount option allows the kernel to skip the super flags check,
it's mostly to allow the kernel to do a rescue mount of an interrupted
checksum conversion.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/fs.h
fs/btrfs/super.c
fs/btrfs/sysfs.c

index 2cfb7ab24aa9e3ffe078e526da9e57650c84022a..382a27ce3aac525711f600e90c03e5096ece77f7 100644 (file)
@@ -2345,15 +2345,23 @@ int btrfs_validate_super(const struct btrfs_fs_info *fs_info,
        u64 nodesize = btrfs_super_nodesize(sb);
        u64 sectorsize = btrfs_super_sectorsize(sb);
        int ret = 0;
+       const bool ignore_flags = btrfs_test_opt(fs_info, IGNORESUPERFLAGS);
 
        if (btrfs_super_magic(sb) != BTRFS_MAGIC) {
                btrfs_err(fs_info, "no valid FS found");
                ret = -EINVAL;
        }
-       if (btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP) {
-               btrfs_err(fs_info, "unrecognized or unsupported super flag: 0x%llx",
-                               btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
-               ret = -EINVAL;
+       if ((btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP)) {
+               if (!ignore_flags) {
+                       btrfs_err(fs_info,
+                       "unrecognized or unsupported super flag 0x%llx",
+                                 btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
+                       ret = -EINVAL;
+               } else {
+                       btrfs_info(fs_info,
+                       "unrecognized or unsupported super flags: 0x%llx, ignored",
+                                  btrfs_super_flags(sb) & ~BTRFS_SUPER_FLAG_SUPP);
+               }
        }
        if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
                btrfs_err(fs_info, "tree_root level too big: %d >= %d",
index d5d473aafe984da30b64bd53139ff8bd544fd1fb..e911e0a838a20098f0d412be2e274cce75594e80 100644 (file)
@@ -227,6 +227,7 @@ enum {
        BTRFS_MOUNT_NODISCARD                   = (1UL << 29),
        BTRFS_MOUNT_NOSPACECACHE                = (1UL << 30),
        BTRFS_MOUNT_IGNOREMETACSUMS             = (1UL << 31),
+       BTRFS_MOUNT_IGNORESUPERFLAGS            = (1ULL << 32),
 };
 
 /*
index 65d2abdc9975e57dc9cca25b8fcb217ae0f20f46..0eda8c21d8613d9de1acdcac954fa6d6db9e54d2 100644 (file)
@@ -177,6 +177,7 @@ enum {
        Opt_rescue_ignorebadroots,
        Opt_rescue_ignoredatacsums,
        Opt_rescue_ignoremetacsums,
+       Opt_rescue_ignoresuperflags,
        Opt_rescue_parameter_all,
 };
 
@@ -187,8 +188,10 @@ static const struct constant_table btrfs_parameter_rescue[] = {
        { "ibadroots", Opt_rescue_ignorebadroots },
        { "ignoredatacsums", Opt_rescue_ignoredatacsums },
        { "ignoremetacsums", Opt_rescue_ignoremetacsums},
+       { "ignoresuperflags", Opt_rescue_ignoresuperflags},
        { "idatacsums", Opt_rescue_ignoredatacsums },
        { "imetacsums", Opt_rescue_ignoremetacsums},
+       { "isuperflags", Opt_rescue_ignoresuperflags},
        { "all", Opt_rescue_parameter_all },
        {}
 };
@@ -577,9 +580,13 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
                case Opt_rescue_ignoremetacsums:
                        btrfs_set_opt(ctx->mount_opt, IGNOREMETACSUMS);
                        break;
+               case Opt_rescue_ignoresuperflags:
+                       btrfs_set_opt(ctx->mount_opt, IGNORESUPERFLAGS);
+                       break;
                case Opt_rescue_parameter_all:
                        btrfs_set_opt(ctx->mount_opt, IGNOREDATACSUMS);
                        btrfs_set_opt(ctx->mount_opt, IGNOREMETACSUMS);
+                       btrfs_set_opt(ctx->mount_opt, IGNORESUPERFLAGS);
                        btrfs_set_opt(ctx->mount_opt, IGNOREBADROOTS);
                        btrfs_set_opt(ctx->mount_opt, NOLOGREPLAY);
                        break;
@@ -655,7 +662,8 @@ bool btrfs_check_options(const struct btrfs_fs_info *info, unsigned long *mount_
            (check_ro_option(info, *mount_opt, BTRFS_MOUNT_NOLOGREPLAY, "nologreplay") ||
             check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREBADROOTS, "ignorebadroots") ||
             check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREDATACSUMS, "ignoredatacsums") ||
-            check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREMETACSUMS, "ignoremetacsums")))
+            check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREMETACSUMS, "ignoremetacsums") ||
+            check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNORESUPERFLAGS, "ignoresuperflags")))
                ret = false;
 
        if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE) &&
@@ -1073,6 +1081,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                print_rescue_option(seq, "ignoredatacsums", &printed);
        if (btrfs_test_opt(info, IGNOREMETACSUMS))
                print_rescue_option(seq, "ignoremetacsums", &printed);
+       if (btrfs_test_opt(info, IGNORESUPERFLAGS))
+               print_rescue_option(seq, "ignoresuperflags", &printed);
        if (btrfs_test_opt(info, FLUSHONCOMMIT))
                seq_puts(seq, ",flushoncommit");
        if (btrfs_test_opt(info, DISCARD_SYNC))
@@ -1431,6 +1441,7 @@ static void btrfs_emit_options(struct btrfs_fs_info *info,
        btrfs_info_if_set(info, old, IGNOREBADROOTS, "ignoring bad roots");
        btrfs_info_if_set(info, old, IGNOREDATACSUMS, "ignoring data csums");
        btrfs_info_if_set(info, old, IGNOREMETACSUMS, "ignoring meta csums");
+       btrfs_info_if_set(info, old, IGNORESUPERFLAGS, "ignoring unknown super block flags");
 
        btrfs_info_if_unset(info, old, NODATACOW, "setting datacow");
        btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations");
index 0e0e8eb84ca2dbe3a7b33913058e5fac1f9affa5..03926ad467c919f7beae95f7c66f9c76496773c8 100644 (file)
@@ -386,6 +386,7 @@ static const char *rescue_opts[] = {
        "ignorebadroots",
        "ignoredatacsums",
        "ignoremetacsums",
+       "ignoresuperflags",
        "all",
 };