diff options
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 115 | 
1 files changed, 62 insertions, 53 deletions
| diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 81107ad49f3a..6601c9aa5e35 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -5,7 +5,6 @@  #include <linux/blkdev.h>  #include <linux/module.h> -#include <linux/buffer_head.h>  #include <linux/fs.h>  #include <linux/pagemap.h>  #include <linux/highmem.h> @@ -15,8 +14,6 @@  #include <linux/string.h>  #include <linux/backing-dev.h>  #include <linux/mount.h> -#include <linux/mpage.h> -#include <linux/swap.h>  #include <linux/writeback.h>  #include <linux/statfs.h>  #include <linux/compat.h> @@ -468,9 +465,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,  		case Opt_subvolrootid:  		case Opt_device:  			/* -			 * These are parsed by btrfs_parse_subvol_options -			 * and btrfs_parse_early_options -			 * and can be happily ignored here. +			 * These are parsed by btrfs_parse_subvol_options or +			 * btrfs_parse_device_options and can be ignored here.  			 */  			break;  		case Opt_nodatasum: @@ -760,6 +756,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,  		case Opt_recovery:  			btrfs_warn(info,  				   "'recovery' is deprecated, use 'usebackuproot' instead"); +			/* fall through */  		case Opt_usebackuproot:  			btrfs_info(info,  				   "trying to use backup root at mount time"); @@ -885,13 +882,16 @@ out:   * All other options will be parsed on much later in the mount process and   * only when we need to allocate a new super block.   */ -static int btrfs_parse_early_options(const char *options, fmode_t flags, -		void *holder, struct btrfs_fs_devices **fs_devices) +static int btrfs_parse_device_options(const char *options, fmode_t flags, +				      void *holder)  {  	substring_t args[MAX_OPT_ARGS];  	char *device_name, *opts, *orig, *p; +	struct btrfs_device *device = NULL;  	int error = 0; +	lockdep_assert_held(&uuid_mutex); +  	if (!options)  		return 0; @@ -917,11 +917,13 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,  				error = -ENOMEM;  				goto out;  			} -			error = btrfs_scan_one_device(device_name, -					flags, holder, fs_devices); +			device = btrfs_scan_one_device(device_name, flags, +					holder);  			kfree(device_name); -			if (error) +			if (IS_ERR(device)) { +				error = PTR_ERR(device);  				goto out; +			}  		}  	} @@ -935,8 +937,8 @@ out:   *   * The value is later passed to mount_subvol()   */ -static int btrfs_parse_subvol_options(const char *options, fmode_t flags, -		char **subvol_name, u64 *subvol_objectid) +static int btrfs_parse_subvol_options(const char *options, char **subvol_name, +		u64 *subvol_objectid)  {  	substring_t args[MAX_OPT_ARGS];  	char *opts, *orig, *p; @@ -948,7 +950,7 @@ static int btrfs_parse_subvol_options(const char *options, fmode_t flags,  	/*  	 * strsep changes the string, duplicate it because -	 * btrfs_parse_early_options gets called later +	 * btrfs_parse_device_options gets called later  	 */  	opts = kstrdup(options, GFP_KERNEL);  	if (!opts) @@ -1517,6 +1519,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,  {  	struct block_device *bdev = NULL;  	struct super_block *s; +	struct btrfs_device *device = NULL;  	struct btrfs_fs_devices *fs_devices = NULL;  	struct btrfs_fs_info *fs_info = NULL;  	struct security_mnt_opts new_sec_opts; @@ -1526,12 +1529,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,  	if (!(flags & SB_RDONLY))  		mode |= FMODE_WRITE; -	error = btrfs_parse_early_options(data, mode, fs_type, -					  &fs_devices); -	if (error) { -		return ERR_PTR(error); -	} -  	security_init_mnt_opts(&new_sec_opts);  	if (data) {  		error = parse_security_options(data, &new_sec_opts); @@ -1539,10 +1536,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,  			return ERR_PTR(error);  	} -	error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices); -	if (error) -		goto error_sec_opts; -  	/*  	 * Setup a dummy root and fs_info for test/set super.  This is because  	 * we don't actually fill this stuff out until open_ctree, but we need @@ -1555,8 +1548,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,  		goto error_sec_opts;  	} -	fs_info->fs_devices = fs_devices; -  	fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);  	fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);  	security_init_mnt_opts(&fs_info->security_opts); @@ -1565,7 +1556,25 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,  		goto error_fs_info;  	} +	mutex_lock(&uuid_mutex); +	error = btrfs_parse_device_options(data, mode, fs_type); +	if (error) { +		mutex_unlock(&uuid_mutex); +		goto error_fs_info; +	} + +	device = btrfs_scan_one_device(device_name, mode, fs_type); +	if (IS_ERR(device)) { +		mutex_unlock(&uuid_mutex); +		error = PTR_ERR(device); +		goto error_fs_info; +	} + +	fs_devices = device->fs_devices; +	fs_info->fs_devices = fs_devices; +  	error = btrfs_open_devices(fs_devices, mode, fs_type); +	mutex_unlock(&uuid_mutex);  	if (error)  		goto error_fs_info; @@ -1650,8 +1659,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  	if (!(flags & SB_RDONLY))  		mode |= FMODE_WRITE; -	error = btrfs_parse_subvol_options(data, mode, -					  &subvol_name, &subvol_objectid); +	error = btrfs_parse_subvol_options(data, &subvol_name, +					&subvol_objectid);  	if (error) {  		kfree(subvol_name);  		return ERR_PTR(error); @@ -2098,14 +2107,9 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)  				btrfs_account_ro_block_groups_free_space(found);  			for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { -				if (!list_empty(&found->block_groups[i])) { -					switch (i) { -					case BTRFS_RAID_DUP: -					case BTRFS_RAID_RAID1: -					case BTRFS_RAID_RAID10: -						factor = 2; -					} -				} +				if (!list_empty(&found->block_groups[i])) +					factor = btrfs_bg_type_to_factor( +						btrfs_raid_array[i].bg_flag);  			}  		} @@ -2222,7 +2226,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,  				unsigned long arg)  {  	struct btrfs_ioctl_vol_args *vol; -	struct btrfs_fs_devices *fs_devices; +	struct btrfs_device *device = NULL;  	int ret = -ENOTTY;  	if (!capable(CAP_SYS_ADMIN)) @@ -2234,15 +2238,24 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,  	switch (cmd) {  	case BTRFS_IOC_SCAN_DEV: -		ret = btrfs_scan_one_device(vol->name, FMODE_READ, -					    &btrfs_root_fs_type, &fs_devices); +		mutex_lock(&uuid_mutex); +		device = btrfs_scan_one_device(vol->name, FMODE_READ, +					       &btrfs_root_fs_type); +		ret = PTR_ERR_OR_ZERO(device); +		mutex_unlock(&uuid_mutex);  		break;  	case BTRFS_IOC_DEVICES_READY: -		ret = btrfs_scan_one_device(vol->name, FMODE_READ, -					    &btrfs_root_fs_type, &fs_devices); -		if (ret) +		mutex_lock(&uuid_mutex); +		device = btrfs_scan_one_device(vol->name, FMODE_READ, +					       &btrfs_root_fs_type); +		if (IS_ERR(device)) { +			mutex_unlock(&uuid_mutex); +			ret = PTR_ERR(device);  			break; -		ret = !(fs_devices->num_devices == fs_devices->total_devices); +		} +		ret = !(device->fs_devices->num_devices == +			device->fs_devices->total_devices); +		mutex_unlock(&uuid_mutex);  		break;  	case BTRFS_IOC_GET_SUPPORTED_FEATURES:  		ret = btrfs_ioctl_get_supported_features((void __user*)arg); @@ -2290,7 +2303,6 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)  	struct btrfs_fs_devices *cur_devices;  	struct btrfs_device *dev, *first_dev = NULL;  	struct list_head *head; -	struct rcu_string *name;  	/*  	 * Lightweight locking of the devices. We should not need @@ -2314,12 +2326,10 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)  		cur_devices = cur_devices->seed;  	} -	if (first_dev) { -		name = rcu_dereference(first_dev->name); -		seq_escape(m, name->str, " \t\n\\"); -	} else { +	if (first_dev) +		seq_escape(m, rcu_str_deref(first_dev->name), " \t\n\\"); +	else  		WARN_ON(1); -	}  	rcu_read_unlock();  	return 0;  } @@ -2331,7 +2341,6 @@ static const struct super_operations btrfs_super_ops = {  	.sync_fs	= btrfs_sync_fs,  	.show_options	= btrfs_show_options,  	.show_devname	= btrfs_show_devname, -	.write_inode	= btrfs_write_inode,  	.alloc_inode	= btrfs_alloc_inode,  	.destroy_inode	= btrfs_destroy_inode,  	.statfs		= btrfs_statfs, @@ -2369,7 +2378,7 @@ static __cold void btrfs_interface_exit(void)  static void __init btrfs_print_mod_info(void)  { -	pr_info("Btrfs loaded, crc32c=%s" +	static const char options[] = ""  #ifdef CONFIG_BTRFS_DEBUG  			", debug=on"  #endif @@ -2382,8 +2391,8 @@ static void __init btrfs_print_mod_info(void)  #ifdef CONFIG_BTRFS_FS_REF_VERIFY  			", ref-verify=on"  #endif -			"\n", -			crc32c_impl()); +			; +	pr_info("Btrfs loaded, crc32c=%s%s\n", crc32c_impl(), options);  }  static int __init init_btrfs_fs(void) |