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

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
...@@ -168,6 +168,14 @@ Options with (*) are default options and will not show in the mount options. ...@@ -168,6 +168,14 @@ Options with (*) are default options and will not show in the mount options.
notreelog notreelog
Enable/disable the tree logging used for fsync and O_SYNC writes. 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 usebackuproot
Enable attempts to use backup tree roots if a bad tree root is found at Enable attempts to use backup tree roots if a bad tree root is found at
mount time. mount time.
......
...@@ -2250,6 +2250,7 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -2250,6 +2250,7 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_MOUNT_FRAGMENT_DATA (1 << 24) #define BTRFS_MOUNT_FRAGMENT_DATA (1 << 24)
#define BTRFS_MOUNT_FRAGMENT_METADATA (1 << 25) #define BTRFS_MOUNT_FRAGMENT_METADATA (1 << 25)
#define BTRFS_MOUNT_FREE_SPACE_TREE (1 << 26) #define BTRFS_MOUNT_FREE_SPACE_TREE (1 << 26)
#define BTRFS_MOUNT_NOLOGREPLAY (1 << 27)
#define BTRFS_DEFAULT_COMMIT_INTERVAL (30) #define BTRFS_DEFAULT_COMMIT_INTERVAL (30)
#define BTRFS_DEFAULT_MAX_INLINE (8192) #define BTRFS_DEFAULT_MAX_INLINE (8192)
...@@ -4151,7 +4152,8 @@ void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info); ...@@ -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); ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
/* super.c */ /* 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); int btrfs_sync_fs(struct super_block *sb, int wait);
#ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK
......
...@@ -2750,7 +2750,7 @@ int open_ctree(struct super_block *sb, ...@@ -2750,7 +2750,7 @@ int open_ctree(struct super_block *sb,
*/ */
fs_info->compress_type = BTRFS_COMPRESS_ZLIB; 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) { if (ret) {
err = ret; err = ret;
goto fail_alloc; goto fail_alloc;
...@@ -3029,8 +3029,9 @@ int open_ctree(struct super_block *sb, ...@@ -3029,8 +3029,9 @@ int open_ctree(struct super_block *sb,
if (ret) if (ret)
goto fail_trans_kthread; goto fail_trans_kthread;
/* do not make disk changes in broken FS */ /* do not make disk changes in broken FS or nologreplay is given */
if (btrfs_super_log_root(disk_super) != 0) { if (btrfs_super_log_root(disk_super) != 0 &&
!btrfs_test_opt(tree_root, NOLOGREPLAY)) {
ret = btrfs_replay_log(fs_info, fs_devices); ret = btrfs_replay_log(fs_info, fs_devices);
if (ret) { if (ret) {
err = ret; err = ret;
......
...@@ -304,6 +304,7 @@ enum { ...@@ -304,6 +304,7 @@ enum {
Opt_commit_interval, Opt_barrier, Opt_nodefrag, Opt_nodiscard, Opt_commit_interval, Opt_barrier, Opt_nodefrag, Opt_nodiscard,
Opt_noenospc_debug, Opt_noflushoncommit, Opt_acl, Opt_datacow, Opt_noenospc_debug, Opt_noflushoncommit, Opt_acl, Opt_datacow,
Opt_datasum, Opt_treelog, Opt_noinode_cache, Opt_usebackuproot, Opt_datasum, Opt_treelog, Opt_noinode_cache, Opt_usebackuproot,
Opt_nologreplay,
#ifdef CONFIG_BTRFS_DEBUG #ifdef CONFIG_BTRFS_DEBUG
Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all, Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all,
#endif #endif
...@@ -335,6 +336,7 @@ static const match_table_t tokens = { ...@@ -335,6 +336,7 @@ static const match_table_t tokens = {
{Opt_noacl, "noacl"}, {Opt_noacl, "noacl"},
{Opt_notreelog, "notreelog"}, {Opt_notreelog, "notreelog"},
{Opt_treelog, "treelog"}, {Opt_treelog, "treelog"},
{Opt_nologreplay, "nologreplay"},
{Opt_flushoncommit, "flushoncommit"}, {Opt_flushoncommit, "flushoncommit"},
{Opt_noflushoncommit, "noflushoncommit"}, {Opt_noflushoncommit, "noflushoncommit"},
{Opt_ratio, "metadata_ratio=%d"}, {Opt_ratio, "metadata_ratio=%d"},
...@@ -374,7 +376,8 @@ static const match_table_t tokens = { ...@@ -374,7 +376,8 @@ static const match_table_t tokens = {
* reading in a new superblock is parsed here. * reading in a new superblock is parsed here.
* XXX JDM: This needs to be cleaned up for remount. * 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; struct btrfs_fs_info *info = root->fs_info;
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
...@@ -394,8 +397,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -394,8 +397,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
else if (cache_gen) else if (cache_gen)
btrfs_set_opt(info->mount_opt, SPACE_CACHE); 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) if (!options)
goto out; goto check;
/* /*
* strsep changes the string, duplicate it because parse_options * strsep changes the string, duplicate it because parse_options
...@@ -607,6 +614,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -607,6 +614,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
btrfs_clear_and_info(root, NOTREELOG, btrfs_clear_and_info(root, NOTREELOG,
"enabling tree log"); "enabling tree log");
break; break;
case Opt_nologreplay:
btrfs_set_and_info(root, NOLOGREPLAY,
"disabling log replay at mount time");
break;
case Opt_flushoncommit: case Opt_flushoncommit:
btrfs_set_and_info(root, FLUSHONCOMMIT, btrfs_set_and_info(root, FLUSHONCOMMIT,
"turning on flush-on-commit"); "turning on flush-on-commit");
...@@ -797,6 +808,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -797,6 +808,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
break; 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: out:
if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE) && if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE) &&
!btrfs_test_opt(root, 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) ...@@ -1207,6 +1227,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
seq_puts(seq, ",ssd"); seq_puts(seq, ",ssd");
if (btrfs_test_opt(root, NOTREELOG)) if (btrfs_test_opt(root, NOTREELOG))
seq_puts(seq, ",notreelog"); seq_puts(seq, ",notreelog");
if (btrfs_test_opt(root, NOLOGREPLAY))
seq_puts(seq, ",nologreplay");
if (btrfs_test_opt(root, FLUSHONCOMMIT)) if (btrfs_test_opt(root, FLUSHONCOMMIT))
seq_puts(seq, ",flushoncommit"); seq_puts(seq, ",flushoncommit");
if (btrfs_test_opt(root, DISCARD)) if (btrfs_test_opt(root, DISCARD))
...@@ -1688,7 +1710,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -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) { if (ret) {
ret = -EINVAL; ret = -EINVAL;
goto restore; goto restore;
......
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