mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: Qu Wenruo <quwenruo@cn.fujitsu.com> Reviewed-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> Tested-by: Austin S. Hemmelgarn <ahferroin7@gmail.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									8dcddfa048
								
							
						
					
					
						commit
						96da09192c
					
				
					 4 changed files with 40 additions and 7 deletions
				
			
		| 
						 | 
					@ -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 {
 | 
				
			||||||
#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);
 | 
				
			||||||
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,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	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,
 | 
				
			||||||
	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 {
 | 
				
			||||||
	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 = {
 | 
				
			||||||
	{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 = {
 | 
				
			||||||
 * 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)
 | 
				
			||||||
	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)
 | 
				
			||||||
			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)
 | 
				
			||||||
			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)
 | 
				
			||||||
		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)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue