Commit 74ef0018 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: introduce "rescue=" mount option



This patch introduces a new "rescue=" mount option group for all mount
options for data recovery.

Different rescue sub options are seperated by ':'. E.g
"ro,rescue=nologreplay:usebackuproot".

The original plan was to use ';', but ';' needs to be escaped/quoted,
or it will be interpreted by bash, similar to '|'.

And obviously, user can specify rescue options one by one like:
"ro,rescue=nologreplay,rescue=usebackuproot".

The following mount options are converted to "rescue=", old mount
options are deprecated but still available for compatibility purpose:

- usebackuproot
  Now it's "rescue=usebackuproot"

- nologreplay
  Now it's "rescue=nologreplay"

Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent a89ef455
Loading
Loading
Loading
Loading
+73 −8
Original line number Diff line number Diff line
@@ -326,7 +326,6 @@ enum {
	Opt_defrag, Opt_nodefrag,
	Opt_discard, Opt_nodiscard,
	Opt_discard_mode,
	Opt_nologreplay,
	Opt_norecovery,
	Opt_ratio,
	Opt_rescan_uuid_tree,
@@ -340,9 +339,13 @@ enum {
	Opt_subvolid,
	Opt_thread_pool,
	Opt_treelog, Opt_notreelog,
	Opt_usebackuproot,
	Opt_user_subvol_rm_allowed,

	/* Rescue options */
	Opt_rescue,
	Opt_usebackuproot,
	Opt_nologreplay,

	/* Deprecated options */
	Opt_alloc_start,
	Opt_recovery,
@@ -390,7 +393,6 @@ static const match_table_t tokens = {
	{Opt_discard, "discard"},
	{Opt_discard_mode, "discard=%s"},
	{Opt_nodiscard, "nodiscard"},
	{Opt_nologreplay, "nologreplay"},
	{Opt_norecovery, "norecovery"},
	{Opt_ratio, "metadata_ratio=%u"},
	{Opt_rescan_uuid_tree, "rescan_uuid_tree"},
@@ -408,9 +410,15 @@ static const match_table_t tokens = {
	{Opt_thread_pool, "thread_pool=%u"},
	{Opt_treelog, "treelog"},
	{Opt_notreelog, "notreelog"},
	{Opt_usebackuproot, "usebackuproot"},
	{Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},

	/* Rescue options */
	{Opt_rescue, "rescue=%s"},
	/* Deprecated, with alias rescue=nologreplay */
	{Opt_nologreplay, "nologreplay"},
	/* Deprecated, with alias rescue=usebackuproot */
	{Opt_usebackuproot, "usebackuproot"},

	/* Deprecated options */
	{Opt_alloc_start, "alloc_start=%s"},
	{Opt_recovery, "recovery"},
@@ -433,6 +441,55 @@ static const match_table_t tokens = {
	{Opt_err, NULL},
};

static const match_table_t rescue_tokens = {
	{Opt_usebackuproot, "usebackuproot"},
	{Opt_nologreplay, "nologreplay"},
	{Opt_err, NULL},
};

static int parse_rescue_options(struct btrfs_fs_info *info, const char *options)
{
	char *opts;
	char *orig;
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int ret = 0;

	opts = kstrdup(options, GFP_KERNEL);
	if (!opts)
		return -ENOMEM;
	orig = opts;

	while ((p = strsep(&opts, ":")) != NULL) {
		int token;

		if (!*p)
			continue;
		token = match_token(p, rescue_tokens, args);
		switch (token){
		case Opt_usebackuproot:
			btrfs_info(info,
				   "trying to use backup root at mount time");
			btrfs_set_opt(info->mount_opt, USEBACKUPROOT);
			break;
		case Opt_nologreplay:
			btrfs_set_and_info(info, NOLOGREPLAY,
					   "disabling log replay at mount time");
			break;
		case Opt_err:
			btrfs_info(info, "unrecognized rescue option '%s'", p);
			ret = -EINVAL;
			goto out;
		default:
			break;
		}

	}
out:
	kfree(orig);
	return ret;
}

/*
 * Regular mount options parser.  Everything that is needed only when
 * reading in a new superblock is parsed here.
@@ -689,6 +746,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
			break;
		case Opt_norecovery:
		case Opt_nologreplay:
			btrfs_warn(info,
		"'nologreplay' is deprecated, use 'rescue=nologreplay' instead");
			btrfs_set_and_info(info, NOLOGREPLAY,
					   "disabling log replay at mount time");
			break;
@@ -791,10 +850,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
					     "disabling auto defrag");
			break;
		case Opt_recovery:
			btrfs_warn(info,
				   "'recovery' is deprecated, use 'usebackuproot' instead");
			fallthrough;
		case Opt_usebackuproot:
			btrfs_warn(info,
			"'%s' is deprecated, use 'rescue=usebackuproot' instead",
				   token == Opt_recovery ? "recovery" :
				   "usebackuproot");
			btrfs_info(info,
				   "trying to use backup root at mount time");
			btrfs_set_opt(info->mount_opt, USEBACKUPROOT);
@@ -859,6 +919,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
			}
			info->commit_interval = intarg;
			break;
		case Opt_rescue:
			ret = parse_rescue_options(info, args[0].from);
			if (ret < 0)
				goto out;
			break;
#ifdef CONFIG_BTRFS_DEBUG
		case Opt_fragment_all:
			btrfs_info(info, "fragmenting all space");
@@ -1344,7 +1409,7 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
	if (btrfs_test_opt(info, NOTREELOG))
		seq_puts(seq, ",notreelog");
	if (btrfs_test_opt(info, NOLOGREPLAY))
		seq_puts(seq, ",nologreplay");
		seq_puts(seq, ",rescue=nologreplay");
	if (btrfs_test_opt(info, FLUSHONCOMMIT))
		seq_puts(seq, ",flushoncommit");
	if (btrfs_test_opt(info, DISCARD_SYNC))