btrfs: reorder initialization before the mount locks uuid_mutex
[sfrench/cifs-2.6.git] / fs / btrfs / super.c
index 3c5f221b5303a9477e3dd00bea5156ab5986e090..d33fc1fc42858a48c8b94f837b37b0a33181d843 100644 (file)
@@ -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>
@@ -893,6 +890,8 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
        char *device_name, *opts, *orig, *p;
        int error = 0;
 
+       lockdep_assert_held(&uuid_mutex);
+
        if (!options)
                return 0;
 
@@ -936,8 +935,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;
@@ -1527,12 +1526,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);
@@ -1540,10 +1533,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
@@ -1556,8 +1545,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);
@@ -1566,7 +1553,23 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
                goto error_fs_info;
        }
 
+       mutex_lock(&uuid_mutex);
+       error = btrfs_parse_early_options(data, mode, fs_type, &fs_devices);
+       mutex_unlock(&uuid_mutex);
+       if (error)
+               goto error_fs_info;
+
+       mutex_lock(&uuid_mutex);
+       error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices);
+       mutex_unlock(&uuid_mutex);
+       if (error)
+               goto error_fs_info;
+
+       fs_info->fs_devices = fs_devices;
+
+       mutex_lock(&uuid_mutex);
        error = btrfs_open_devices(fs_devices, mode, fs_type);
+       mutex_unlock(&uuid_mutex);
        if (error)
                goto error_fs_info;
 
@@ -1651,8 +1654,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);
@@ -2235,15 +2238,21 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
 
        switch (cmd) {
        case BTRFS_IOC_SCAN_DEV:
+               mutex_lock(&uuid_mutex);
                ret = btrfs_scan_one_device(vol->name, FMODE_READ,
                                            &btrfs_root_fs_type, &fs_devices);
+               mutex_unlock(&uuid_mutex);
                break;
        case BTRFS_IOC_DEVICES_READY:
+               mutex_lock(&uuid_mutex);
                ret = btrfs_scan_one_device(vol->name, FMODE_READ,
                                            &btrfs_root_fs_type, &fs_devices);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&uuid_mutex);
                        break;
+               }
                ret = !(fs_devices->num_devices == fs_devices->total_devices);
+               mutex_unlock(&uuid_mutex);
                break;
        case BTRFS_IOC_GET_SUPPORTED_FEATURES:
                ret = btrfs_ioctl_get_supported_features((void __user*)arg);