Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96da0919 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: Introduce new mount option to disable tree log replay



Introduce a new mount option "nologreplay" to co-operate with "ro" mount
option to get real readonly mount, like "norecovery" in ext* and xfs.

Since the new parse_options() need to check new flags at remount time,
so add a new parameter for parse_options().

Signed-off-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
Reviewed-by: default avatarChandan Rajendra <chandan@linux.vnet.ibm.com>
Tested-by: default avatarAustin S. Hemmelgarn <ahferroin7@gmail.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 8dcddfa0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -168,6 +168,14 @@ Options with (*) are default options and will not show in the mount options.
  notreelog
	Enable/disable the tree logging used for fsync and O_SYNC writes.

  nologreplay
	Disable the log tree replay at mount time to prevent filesystem
	from getting modified.
	Must be used with 'ro' mount option.
	A filesystem mounted with this option cannot transition to a
	read-write mount via remount,rw - the filesystem must be unmounted
	and mounted back again if read-write access is desired.

  usebackuproot
	Enable attempts to use backup tree roots if a bad tree root is found at
	mount time.
+3 −1
Original line number Diff line number Diff line
@@ -2250,6 +2250,7 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_MOUNT_FRAGMENT_DATA	(1 << 24)
#define BTRFS_MOUNT_FRAGMENT_METADATA	(1 << 25)
#define BTRFS_MOUNT_FREE_SPACE_TREE	(1 << 26)
#define BTRFS_MOUNT_NOLOGREPLAY		(1 << 27)

#define BTRFS_DEFAULT_COMMIT_INTERVAL	(30)
#define BTRFS_DEFAULT_MAX_INLINE	(8192)
@@ -4151,7 +4152,8 @@ void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info);
ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);

/* super.c */
int btrfs_parse_options(struct btrfs_root *root, char *options);
int btrfs_parse_options(struct btrfs_root *root, char *options,
			unsigned long new_flags);
int btrfs_sync_fs(struct super_block *sb, int wait);

#ifdef CONFIG_PRINTK
+4 −3
Original line number Diff line number Diff line
@@ -2750,7 +2750,7 @@ int open_ctree(struct super_block *sb,
	 */
	fs_info->compress_type = BTRFS_COMPRESS_ZLIB;

	ret = btrfs_parse_options(tree_root, options);
	ret = btrfs_parse_options(tree_root, options, sb->s_flags);
	if (ret) {
		err = ret;
		goto fail_alloc;
@@ -3029,8 +3029,9 @@ int open_ctree(struct super_block *sb,
	if (ret)
		goto fail_trans_kthread;

	/* do not make disk changes in broken FS */
	if (btrfs_super_log_root(disk_super) != 0) {
	/* do not make disk changes in broken FS or nologreplay is given */
	if (btrfs_super_log_root(disk_super) != 0 &&
	    !btrfs_test_opt(tree_root, NOLOGREPLAY)) {
		ret = btrfs_replay_log(fs_info, fs_devices);
		if (ret) {
			err = ret;
+25 −3
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@ enum {
	Opt_commit_interval, Opt_barrier, Opt_nodefrag, Opt_nodiscard,
	Opt_noenospc_debug, Opt_noflushoncommit, Opt_acl, Opt_datacow,
	Opt_datasum, Opt_treelog, Opt_noinode_cache, Opt_usebackuproot,
	Opt_nologreplay,
#ifdef CONFIG_BTRFS_DEBUG
	Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all,
#endif
@@ -335,6 +336,7 @@ static const match_table_t tokens = {
	{Opt_noacl, "noacl"},
	{Opt_notreelog, "notreelog"},
	{Opt_treelog, "treelog"},
	{Opt_nologreplay, "nologreplay"},
	{Opt_flushoncommit, "flushoncommit"},
	{Opt_noflushoncommit, "noflushoncommit"},
	{Opt_ratio, "metadata_ratio=%d"},
@@ -374,7 +376,8 @@ static const match_table_t tokens = {
 * reading in a new superblock is parsed here.
 * XXX JDM: This needs to be cleaned up for remount.
 */
int btrfs_parse_options(struct btrfs_root *root, char *options)
int btrfs_parse_options(struct btrfs_root *root, char *options,
			unsigned long new_flags)
{
	struct btrfs_fs_info *info = root->fs_info;
	substring_t args[MAX_OPT_ARGS];
@@ -394,8 +397,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
	else if (cache_gen)
		btrfs_set_opt(info->mount_opt, SPACE_CACHE);

	/*
	 * Even the options are empty, we still need to do extra check
	 * against new flags
	 */
	if (!options)
		goto out;
		goto check;

	/*
	 * strsep changes the string, duplicate it because parse_options
@@ -607,6 +614,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
			btrfs_clear_and_info(root, NOTREELOG,
					     "enabling tree log");
			break;
		case Opt_nologreplay:
			btrfs_set_and_info(root, NOLOGREPLAY,
					   "disabling log replay at mount time");
			break;
		case Opt_flushoncommit:
			btrfs_set_and_info(root, FLUSHONCOMMIT,
					   "turning on flush-on-commit");
@@ -797,6 +808,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
			break;
		}
	}
check:
	/*
	 * Extra check for current option against current flag
	 */
	if (btrfs_test_opt(root, NOLOGREPLAY) && !(new_flags & MS_RDONLY)) {
		btrfs_err(root->fs_info,
			  "nologreplay must be used with ro mount option");
		ret = -EINVAL;
	}
out:
	if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE) &&
	    !btrfs_test_opt(root, FREE_SPACE_TREE) &&
@@ -1207,6 +1227,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
		seq_puts(seq, ",ssd");
	if (btrfs_test_opt(root, NOTREELOG))
		seq_puts(seq, ",notreelog");
	if (btrfs_test_opt(root, NOLOGREPLAY))
		seq_puts(seq, ",nologreplay");
	if (btrfs_test_opt(root, FLUSHONCOMMIT))
		seq_puts(seq, ",flushoncommit");
	if (btrfs_test_opt(root, DISCARD))
@@ -1688,7 +1710,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
		}
	}

	ret = btrfs_parse_options(root, data);
	ret = btrfs_parse_options(root, data, *flags);
	if (ret) {
		ret = -EINVAL;
		goto restore;