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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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)
+12 −9
Original line number Diff line number Diff line
@@ -2329,6 +2329,8 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
		btrfs_init_devices_late(fs_info);
	}

	/* 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)) {
@@ -2340,6 +2342,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
			fs_info->csum_root = root;
		}
	}

	/*
	 * This tree can share blocks with some other fs tree during relocation
+11 −1
Original line number Diff line number Diff line
@@ -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 @@ 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) &&
@@ -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))
+1 −0
Original line number Diff line number Diff line
@@ -333,6 +333,7 @@ static const char *rescue_opts[] = {
	"usebackuproot",
	"nologreplay",
	"ignorebadroots",
	"ignoredatacsums",
};

static ssize_t supported_rescue_options_show(struct kobject *kobj,