Message ID | c3cc0815c5756d07201c57063f3759250f662c77.1600961206.git.josef@toxicpanda.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | New rescue mount options | expand |
On 2020/9/24 下午11:32, Josef Bacik wrote: > 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. > > Signed-off-by: Josef Bacik <josef@toxicpanda.com> > --- > fs/btrfs/ctree.h | 1 + > fs/btrfs/disk-io.c | 21 ++++++++++++--------- > fs/btrfs/super.c | 11 ++++++++++- > 3 files changed, 23 insertions(+), 10 deletions(-) > > diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h > index fb3cfd0aaf1e..397f5f6b88a4 100644 > --- a/fs/btrfs/ctree.h > +++ b/fs/btrfs/ctree.h > @@ -1296,6 +1296,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) > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 5deedfb0e5c7..6f9d37567a10 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -2269,16 +2269,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 IGNOREDATASCUMS is set don't bother reading the csum root. */ > + if (!btrfs_test_opt(fs_info, IGNOREDATACSUMS)) { This indeed matches the name, ignoredatacsums, no matter if the data csum matches or not. I guess if the user is using this option, they really don't bother the datacsum and just want to grab whatever they can get. Reviewed-by: Qu Wenruo <wqu@suse.com> Thanks, Qu > + 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; > } > > /* > diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c > index 7cc7a9233f5e..2282f0240c1d 100644 > --- a/fs/btrfs/super.c > +++ b/fs/btrfs/super.c > @@ -361,6 +361,7 @@ enum { > Opt_usebackuproot, > Opt_nologreplay, > Opt_ignorebadroots, > + Opt_ignoredatacsums, > > /* Deprecated options */ > Opt_recovery, > @@ -457,6 +458,7 @@ static const match_table_t rescue_tokens = { > {Opt_usebackuproot, "usebackuproot"}, > {Opt_nologreplay, "nologreplay"}, > {Opt_ignorebadroots, "ignorebadroots"}, > + {Opt_ignoredatacsums, "ignoredatacsums"}, > {Opt_err, NULL}, > }; > > @@ -504,6 +506,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; > @@ -990,7 +996,10 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options, > 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) && >
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fb3cfd0aaf1e..397f5f6b88a4 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1296,6 +1296,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) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5deedfb0e5c7..6f9d37567a10 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2269,16 +2269,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 IGNOREDATASCUMS 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; } /* diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 7cc7a9233f5e..2282f0240c1d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -361,6 +361,7 @@ enum { Opt_usebackuproot, Opt_nologreplay, Opt_ignorebadroots, + Opt_ignoredatacsums, /* Deprecated options */ Opt_recovery, @@ -457,6 +458,7 @@ static const match_table_t rescue_tokens = { {Opt_usebackuproot, "usebackuproot"}, {Opt_nologreplay, "nologreplay"}, {Opt_ignorebadroots, "ignorebadroots"}, + {Opt_ignoredatacsums, "ignoredatacsums"}, {Opt_err, NULL}, }; @@ -504,6 +506,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; @@ -990,7 +996,10 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options, 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) &&
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. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/ctree.h | 1 + fs/btrfs/disk-io.c | 21 ++++++++++++--------- fs/btrfs/super.c | 11 ++++++++++- 3 files changed, 23 insertions(+), 10 deletions(-)