Commit 882dbe0c authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: introduce mount option rescue=ignoredatacsums

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: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 42437a63
...@@ -1299,6 +1299,7 @@ static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info) ...@@ -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_REF_VERIFY (1 << 28)
#define BTRFS_MOUNT_DISCARD_ASYNC (1 << 29) #define BTRFS_MOUNT_DISCARD_ASYNC (1 << 29)
#define BTRFS_MOUNT_IGNOREBADROOTS (1 << 30) #define BTRFS_MOUNT_IGNOREBADROOTS (1 << 30)
#define BTRFS_MOUNT_IGNOREDATACSUMS (1 << 31)
#define BTRFS_DEFAULT_COMMIT_INTERVAL (30) #define BTRFS_DEFAULT_COMMIT_INTERVAL (30)
#define BTRFS_DEFAULT_MAX_INLINE (2048) #define BTRFS_DEFAULT_MAX_INLINE (2048)
......
...@@ -2329,16 +2329,19 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info) ...@@ -2329,16 +2329,19 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
btrfs_init_devices_late(fs_info); btrfs_init_devices_late(fs_info);
} }
location.objectid = BTRFS_CSUM_TREE_OBJECTID; /* If IGNOREDATACSUMS is set don't bother reading the csum root. */
root = btrfs_read_tree_root(tree_root, &location); if (!btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
if (IS_ERR(root)) { location.objectid = BTRFS_CSUM_TREE_OBJECTID;
if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) { root = btrfs_read_tree_root(tree_root, &location);
ret = PTR_ERR(root); if (IS_ERR(root)) {
goto out; 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;
} }
/* /*
......
...@@ -361,6 +361,7 @@ enum { ...@@ -361,6 +361,7 @@ enum {
Opt_usebackuproot, Opt_usebackuproot,
Opt_nologreplay, Opt_nologreplay,
Opt_ignorebadroots, Opt_ignorebadroots,
Opt_ignoredatacsums,
/* Deprecated options */ /* Deprecated options */
Opt_recovery, Opt_recovery,
...@@ -458,6 +459,8 @@ static const match_table_t rescue_tokens = { ...@@ -458,6 +459,8 @@ static const match_table_t rescue_tokens = {
{Opt_nologreplay, "nologreplay"}, {Opt_nologreplay, "nologreplay"},
{Opt_ignorebadroots, "ignorebadroots"}, {Opt_ignorebadroots, "ignorebadroots"},
{Opt_ignorebadroots, "ibadroots"}, {Opt_ignorebadroots, "ibadroots"},
{Opt_ignoredatacsums, "ignoredatacsums"},
{Opt_ignoredatacsums, "idatacsums"},
{Opt_err, NULL}, {Opt_err, NULL},
}; };
...@@ -505,6 +508,10 @@ static int parse_rescue_options(struct btrfs_fs_info *info, const char *options) ...@@ -505,6 +508,10 @@ static int parse_rescue_options(struct btrfs_fs_info *info, const char *options)
btrfs_set_and_info(info, IGNOREBADROOTS, btrfs_set_and_info(info, IGNOREBADROOTS,
"ignoring bad roots"); "ignoring bad roots");
break; break;
case Opt_ignoredatacsums:
btrfs_set_and_info(info, IGNOREDATACSUMS,
"ignoring data csums");
break;
case Opt_err: case Opt_err:
btrfs_info(info, "unrecognized rescue option '%s'", p); btrfs_info(info, "unrecognized rescue option '%s'", p);
ret = -EINVAL; ret = -EINVAL;
...@@ -991,7 +998,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options, ...@@ -991,7 +998,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
goto out; goto out;
if (check_ro_option(info, BTRFS_MOUNT_NOLOGREPLAY, "nologreplay") || 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; ret = -EINVAL;
out: out:
if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE) && 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) ...@@ -1449,6 +1457,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
print_rescue_option(seq, "usebackuproot", &printed); print_rescue_option(seq, "usebackuproot", &printed);
if (btrfs_test_opt(info, IGNOREBADROOTS)) if (btrfs_test_opt(info, IGNOREBADROOTS))
print_rescue_option(seq, "ignorebadroots", &printed); print_rescue_option(seq, "ignorebadroots", &printed);
if (btrfs_test_opt(info, IGNOREDATACSUMS))
print_rescue_option(seq, "ignoredatacsums", &printed);
if (btrfs_test_opt(info, FLUSHONCOMMIT)) if (btrfs_test_opt(info, FLUSHONCOMMIT))
seq_puts(seq, ",flushoncommit"); seq_puts(seq, ",flushoncommit");
if (btrfs_test_opt(info, DISCARD_SYNC)) if (btrfs_test_opt(info, DISCARD_SYNC))
......
...@@ -333,6 +333,7 @@ static const char *rescue_opts[] = { ...@@ -333,6 +333,7 @@ static const char *rescue_opts[] = {
"usebackuproot", "usebackuproot",
"nologreplay", "nologreplay",
"ignorebadroots", "ignorebadroots",
"ignoredatacsums",
}; };
static ssize_t supported_rescue_options_show(struct kobject *kobj, static ssize_t supported_rescue_options_show(struct kobject *kobj,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment