diff options
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 71 | 
1 files changed, 60 insertions, 11 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index a004008f7d28..0ac712efcdf2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -52,6 +52,9 @@  #include "export.h"  #include "compression.h" +#define CREATE_TRACE_POINTS +#include <trace/events/btrfs.h> +  static const struct super_operations btrfs_super_ops;  static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, @@ -155,7 +158,8 @@ enum {  	Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress,  	Opt_compress_type, Opt_compress_force, Opt_compress_force_type,  	Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, -	Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, Opt_err, +	Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, +	Opt_enospc_debug, Opt_subvolrootid, Opt_err,  };  static match_table_t tokens = { @@ -184,6 +188,8 @@ static match_table_t tokens = {  	{Opt_space_cache, "space_cache"},  	{Opt_clear_cache, "clear_cache"},  	{Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, +	{Opt_enospc_debug, "enospc_debug"}, +	{Opt_subvolrootid, "subvolrootid=%d"},  	{Opt_err, NULL},  }; @@ -227,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)  			break;  		case Opt_subvol:  		case Opt_subvolid: +		case Opt_subvolrootid:  		case Opt_device:  			/*  			 * These are parsed by btrfs_parse_early_options @@ -358,6 +365,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)  		case Opt_user_subvol_rm_allowed:  			btrfs_set_opt(info->mount_opt, USER_SUBVOL_RM_ALLOWED);  			break; +		case Opt_enospc_debug: +			btrfs_set_opt(info->mount_opt, ENOSPC_DEBUG); +			break;  		case Opt_err:  			printk(KERN_INFO "btrfs: unrecognized mount option "  			       "'%s'\n", p); @@ -380,7 +390,7 @@ out:   */  static int btrfs_parse_early_options(const char *options, fmode_t flags,  		void *holder, char **subvol_name, u64 *subvol_objectid, -		struct btrfs_fs_devices **fs_devices) +		u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices)  {  	substring_t args[MAX_OPT_ARGS];  	char *opts, *orig, *p; @@ -421,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,  					*subvol_objectid = intarg;  			}  			break; +		case Opt_subvolrootid: +			intarg = 0; +			error = match_int(&args[0], &intarg); +			if (!error) { +				/* we want the original fs_tree */ +				if (!intarg) +					*subvol_rootid = +						BTRFS_FS_TREE_OBJECTID; +				else +					*subvol_rootid = intarg; +			} +			break;  		case Opt_device:  			error = btrfs_scan_one_device(match_strdup(&args[0]),  					flags, holder, fs_devices); @@ -615,6 +637,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait)  	struct btrfs_root *root = btrfs_sb(sb);  	int ret; +	trace_btrfs_sync_fs(wait); +  	if (!wait) {  		filemap_flush(root->fs_info->btree_inode->i_mapping);  		return 0; @@ -634,6 +658,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)  {  	struct btrfs_root *root = btrfs_sb(vfs->mnt_sb);  	struct btrfs_fs_info *info = root->fs_info; +	char *compress_type;  	if (btrfs_test_opt(root, DEGRADED))  		seq_puts(seq, ",degraded"); @@ -652,8 +677,16 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)  	if (info->thread_pool_size !=  min_t(unsigned long,  					     num_online_cpus() + 2, 8))  		seq_printf(seq, ",thread_pool=%d", info->thread_pool_size); -	if (btrfs_test_opt(root, COMPRESS)) -		seq_puts(seq, ",compress"); +	if (btrfs_test_opt(root, COMPRESS)) { +		if (info->compress_type == BTRFS_COMPRESS_ZLIB) +			compress_type = "zlib"; +		else +			compress_type = "lzo"; +		if (btrfs_test_opt(root, FORCE_COMPRESS)) +			seq_printf(seq, ",compress-force=%s", compress_type); +		else +			seq_printf(seq, ",compress=%s", compress_type); +	}  	if (btrfs_test_opt(root, NOSSD))  		seq_puts(seq, ",nossd");  	if (btrfs_test_opt(root, SSD_SPREAD)) @@ -668,6 +701,12 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)  		seq_puts(seq, ",discard");  	if (!(root->fs_info->sb->s_flags & MS_POSIXACL))  		seq_puts(seq, ",noacl"); +	if (btrfs_test_opt(root, SPACE_CACHE)) +		seq_puts(seq, ",space_cache"); +	if (btrfs_test_opt(root, CLEAR_CACHE)) +		seq_puts(seq, ",clear_cache"); +	if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) +		seq_puts(seq, ",user_subvol_rm_allowed");  	return 0;  } @@ -711,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  	fmode_t mode = FMODE_READ;  	char *subvol_name = NULL;  	u64 subvol_objectid = 0; +	u64 subvol_rootid = 0;  	int error = 0;  	if (!(flags & MS_RDONLY)) @@ -718,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  	error = btrfs_parse_early_options(data, mode, fs_type,  					  &subvol_name, &subvol_objectid, -					  &fs_devices); +					  &subvol_rootid, &fs_devices);  	if (error)  		return ERR_PTR(error); @@ -782,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  		s->s_flags |= MS_ACTIVE;  	} -	root = get_default_root(s, subvol_objectid); -	if (IS_ERR(root)) { -		error = PTR_ERR(root); -		deactivate_locked_super(s); -		goto error_free_subvol_name; -	}  	/* if they gave us a subvolume name bind mount into that */  	if (strcmp(subvol_name, ".")) {  		struct dentry *new_root; + +		root = get_default_root(s, subvol_rootid); +		if (IS_ERR(root)) { +			error = PTR_ERR(root); +			deactivate_locked_super(s); +			goto error_free_subvol_name; +		} +  		mutex_lock(&root->d_inode->i_mutex);  		new_root = lookup_one_len(subvol_name, root,  				      strlen(subvol_name)); @@ -811,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  		}  		dput(root);  		root = new_root; +	} else { +		root = get_default_root(s, subvol_objectid); +		if (IS_ERR(root)) { +			error = PTR_ERR(root); +			deactivate_locked_super(s); +			goto error_free_subvol_name; +		}  	}  	kfree(subvol_name);  | 
