btrfs: split parse_early_options() in two

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>
This commit is contained in:
Misono, Tomohiro 2017-12-14 17:25:28 +09:00 committed by David Sterba
parent 312c89fbca
commit d740760656
1 changed files with 57 additions and 25 deletions

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