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) |