]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
btrfs: introduce mount option rescue=ignoredatacsums
authorJosef Bacik <josef@toxicpanda.com>
Fri, 16 Oct 2020 15:29:19 +0000 (11:29 -0400)
committerDavid Sterba <dsterba@suse.com>
Tue, 8 Dec 2020 14:53:42 +0000 (15:53 +0100)
There are cases where you can end up with bad data csums because of
misbehaving applications.  This happens when an application modifies a
buffer in-flight when doing an O_DIRECT write.  In order to recover the
file we need a way to turn off data checksums so you can copy the file
off, and then you can delete the file and restore it properly later.

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

index 683dcb58eaa923141a716fb0e9a37b95bba7f7ae..39e4c35e965ae0a35d7b035c6f0bf7ef1364c18a 100644 (file)
@@ -1299,6 +1299,7 @@ static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info)
 #define BTRFS_MOUNT_REF_VERIFY         (1 << 28)
 #define BTRFS_MOUNT_DISCARD_ASYNC      (1 << 29)
 #define BTRFS_MOUNT_IGNOREBADROOTS     (1 << 30)
+#define BTRFS_MOUNT_IGNOREDATACSUMS    (1 << 31)
 
 #define BTRFS_DEFAULT_COMMIT_INTERVAL  (30)
 #define BTRFS_DEFAULT_MAX_INLINE       (2048)
index d229f6c25f2938ad2fe2dfb06b43bfed0328380d..646dde5883a68c9cc2ad4331406307d4197b33e2 100644 (file)
@@ -2329,16 +2329,19 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
                btrfs_init_devices_late(fs_info);
        }
 
-       location.objectid = BTRFS_CSUM_TREE_OBJECTID;
-       root = btrfs_read_tree_root(tree_root, &location);
-       if (IS_ERR(root)) {
-               if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
-                       ret = PTR_ERR(root);
-                       goto out;
+       /* If IGNOREDATACSUMS is set don't bother reading the csum root. */
+       if (!btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
+               location.objectid = BTRFS_CSUM_TREE_OBJECTID;
+               root = btrfs_read_tree_root(tree_root, &location);
+               if (IS_ERR(root)) {
+                       if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
+                               ret = PTR_ERR(root);
+                               goto out;
+                       }
+               } else {
+                       set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+                       fs_info->csum_root = root;
                }
-       } else {
-               set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-               fs_info->csum_root = root;
        }
 
        /*
index 9bc46c0489789e512549e07a571089bc46f57bbf..6bbd4f04b28df5f9c65e32e7a9de98b23abc8ee8 100644 (file)
@@ -361,6 +361,7 @@ enum {
        Opt_usebackuproot,
        Opt_nologreplay,
        Opt_ignorebadroots,
+       Opt_ignoredatacsums,
 
        /* Deprecated options */
        Opt_recovery,
@@ -458,6 +459,8 @@ static const match_table_t rescue_tokens = {
        {Opt_nologreplay, "nologreplay"},
        {Opt_ignorebadroots, "ignorebadroots"},
        {Opt_ignorebadroots, "ibadroots"},
+       {Opt_ignoredatacsums, "ignoredatacsums"},
+       {Opt_ignoredatacsums, "idatacsums"},
        {Opt_err, NULL},
 };
 
@@ -505,6 +508,10 @@ static int parse_rescue_options(struct btrfs_fs_info *info, const char *options)
                        btrfs_set_and_info(info, IGNOREBADROOTS,
                                           "ignoring bad roots");
                        break;
+               case Opt_ignoredatacsums:
+                       btrfs_set_and_info(info, IGNOREDATACSUMS,
+                                          "ignoring data csums");
+                       break;
                case Opt_err:
                        btrfs_info(info, "unrecognized rescue option '%s'", p);
                        ret = -EINVAL;
@@ -991,7 +998,8 @@ check:
                goto out;
 
        if (check_ro_option(info, BTRFS_MOUNT_NOLOGREPLAY, "nologreplay") ||
-           check_ro_option(info, BTRFS_MOUNT_IGNOREBADROOTS, "ignorebadroots"))
+           check_ro_option(info, BTRFS_MOUNT_IGNOREBADROOTS, "ignorebadroots") ||
+           check_ro_option(info, BTRFS_MOUNT_IGNOREDATACSUMS, "ignoredatacsums"))
                ret = -EINVAL;
 out:
        if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE) &&
@@ -1449,6 +1457,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                print_rescue_option(seq, "usebackuproot", &printed);
        if (btrfs_test_opt(info, IGNOREBADROOTS))
                print_rescue_option(seq, "ignorebadroots", &printed);
+       if (btrfs_test_opt(info, IGNOREDATACSUMS))
+               print_rescue_option(seq, "ignoredatacsums", &printed);
        if (btrfs_test_opt(info, FLUSHONCOMMIT))
                seq_puts(seq, ",flushoncommit");
        if (btrfs_test_opt(info, DISCARD_SYNC))
index e9f4829894151e8d95cfdc94f89f5ab9517a73c1..86f70a60447b2a907ef4c2976b6f3e3e063ec7db 100644 (file)
@@ -333,6 +333,7 @@ static const char *rescue_opts[] = {
        "usebackuproot",
        "nologreplay",
        "ignorebadroots",
+       "ignoredatacsums",
 };
 
 static ssize_t supported_rescue_options_show(struct kobject *kobj,