btrfs: split parse_early_options() in two
authorMisono, Tomohiro <misono.tomohiro@jp.fujitsu.com>
Thu, 14 Dec 2017 08:25:28 +0000 (17:25 +0900)
committerDavid Sterba <dsterba@suse.com>
Mon, 22 Jan 2018 15:08:18 +0000 (16:08 +0100)
Now parse_early_options() is used by both btrfs_mount() and
btrfs_mount_root(). However, the former only needs subvol related part
and the latter needs the others.

Therefore extract the subvol related parts from parse_early_options() and
move it to new parse function (parse_subvol_options()).

Signed-off-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/super.c

index adf0f8b..0d615d0 100644 (file)
@@ -463,7 +463,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                case Opt_subvolrootid:
                case Opt_device:
                        /*
-                        * These are parsed by btrfs_parse_early_options
+                        * These are parsed by btrfs_parse_subvol_options
+                        * and btrfs_parse_early_options
                         * and can be happily ignored here.
                         */
                        break;
@@ -897,11 +898,60 @@ out:
  * only when we need to allocate a new super block.
  */
 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)
+               void *holder, struct btrfs_fs_devices **fs_devices)
 {
        substring_t args[MAX_OPT_ARGS];
        char *device_name, *opts, *orig, *p;
+       int error = 0;
+
+       if (!options)
+               return 0;
+
+       /*
+        * strsep changes the string, duplicate it because btrfs_parse_options
+        * gets called later
+        */
+       opts = kstrdup(options, GFP_KERNEL);
+       if (!opts)
+               return -ENOMEM;
+       orig = opts;
+
+       while ((p = strsep(&opts, ",")) != NULL) {
+               int token;
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               if (token == Opt_device) {
+                       device_name = match_strdup(&args[0]);
+                       if (!device_name) {
+                               error = -ENOMEM;
+                               goto out;
+                       }
+                       error = btrfs_scan_one_device(device_name,
+                                       flags, holder, fs_devices);
+                       kfree(device_name);
+                       if (error)
+                               goto out;
+               }
+       }
+
+out:
+       kfree(orig);
+       return error;
+}
+
+/*
+ * Parse mount options that are related to subvolume id
+ *
+ * The value is later passed to mount_subvol()
+ */
+static int btrfs_parse_subvol_options(const char *options, fmode_t flags,
+               void *holder, char **subvol_name, u64 *subvol_objectid)
+{
+       substring_t args[MAX_OPT_ARGS];
+       char *opts, *orig, *p;
        char *num = NULL;
        int error = 0;
 
@@ -909,8 +959,8 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
                return 0;
 
        /*
-        * strsep changes the string, duplicate it because parse_options
-        * gets called twice
+        * strsep changes the string, duplicate it because
+        * btrfs_parse_early_options gets called later
         */
        opts = kstrdup(options, GFP_KERNEL);
        if (!opts)
@@ -949,18 +999,6 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
                case Opt_subvolrootid:
                        pr_warn("BTRFS: 'subvolrootid' mount option is deprecated and has no effect\n");
                        break;
-               case Opt_device:
-                       device_name = match_strdup(&args[0]);
-                       if (!device_name) {
-                               error = -ENOMEM;
-                               goto out;
-                       }
-                       error = btrfs_scan_one_device(device_name,
-                                       flags, holder, fs_devices);
-                       kfree(device_name);
-                       if (error)
-                               goto out;
-                       break;
                default:
                        break;
                }
@@ -1536,18 +1574,14 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
        struct btrfs_fs_info *fs_info = NULL;
        struct security_mnt_opts new_sec_opts;
        fmode_t mode = FMODE_READ;
-       char *subvol_name = NULL;
-       u64 subvol_objectid = 0;
        int error = 0;
 
        if (!(flags & SB_RDONLY))
                mode |= FMODE_WRITE;
 
        error = btrfs_parse_early_options(data, mode, fs_type,
-                                         &subvol_name, &subvol_objectid,
                                          &fs_devices);
        if (error) {
-               kfree(subvol_name);
                return ERR_PTR(error);
        }
 
@@ -1659,7 +1693,6 @@ error_sec_opts:
 static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                const char *device_name, void *data)
 {
-       struct btrfs_fs_devices *fs_devices = NULL;
        struct vfsmount *mnt_root;
        struct dentry *root;
        fmode_t mode = FMODE_READ;
@@ -1670,9 +1703,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        if (!(flags & SB_RDONLY))
                mode |= FMODE_WRITE;
 
-       error = btrfs_parse_early_options(data, mode, fs_type,
-                                         &subvol_name, &subvol_objectid,
-                                         &fs_devices);
+       error = btrfs_parse_subvol_options(data, mode, fs_type,
+                                         &subvol_name, &subvol_objectid);
        if (error) {
                kfree(subvol_name);
                return ERR_PTR(error);