* [PATCH 1/4] btrfs: add mount_root() and new file_system_type
2017-09-25 7:26 [PATCH v3 0/4] btrfs: cleanup mount path Misono, Tomohiro
@ 2017-09-25 7:27 ` Misono, Tomohiro
2017-12-12 20:07 ` David Sterba
2017-09-25 7:28 ` [PATCH 2/4] btrfs: cleanup btrfs_mount() using mount_root() Misono, Tomohiro
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Misono, Tomohiro @ 2017-09-25 7:27 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba, anand.jain
Add mount_root() and new file_system_type for preparation of cleanup of
btrfs_mount(). Code path is not changed yet.
mount_root() is almost the same as current btrfs_mount(), but doesn't
have subvolume related part.
Signed-off-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
---
fs/btrfs/super.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 12540b6..fe43606 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -66,6 +66,7 @@
static const struct super_operations btrfs_super_ops;
static struct file_system_type btrfs_fs_type;
+static struct file_system_type btrfs_root_fs_type;
static int btrfs_remount(struct super_block *sb, int *flags, char *data);
@@ -1514,6 +1515,112 @@ static int setup_security_options(struct btrfs_fs_info *fs_info,
return ret;
}
+static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
+ const char *device_name, void *data)
+{
+ struct block_device *bdev = NULL;
+ struct super_block *s;
+ struct btrfs_fs_devices *fs_devices = NULL;
+ 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 & MS_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);
+ }
+
+ security_init_mnt_opts(&new_sec_opts);
+ if (data) {
+ error = parse_security_options(data, &new_sec_opts);
+ if (error)
+ 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
+ * it for searching for existing supers, so this lets us do that and
+ * then open_ctree will properly initialize everything later.
+ */
+ fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
+ if (!fs_info) {
+ error = -ENOMEM;
+ goto error_sec_opts;
+ }
+
+ fs_info->fs_devices = fs_devices;
+
+ fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
+ fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
+ security_init_mnt_opts(&fs_info->security_opts);
+ if (!fs_info->super_copy || !fs_info->super_for_commit) {
+ error = -ENOMEM;
+ goto error_fs_info;
+ }
+
+ error = btrfs_open_devices(fs_devices, mode, fs_type);
+ if (error)
+ goto error_fs_info;
+
+ if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
+ error = -EACCES;
+ goto error_close_devices;
+ }
+
+ bdev = fs_devices->latest_bdev;
+ s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | MS_NOSEC,
+ fs_info);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
+ goto error_close_devices;
+ }
+
+ if (s->s_root) {
+ btrfs_close_devices(fs_devices);
+ free_fs_info(fs_info);
+ if ((flags ^ s->s_flags) & MS_RDONLY)
+ error = -EBUSY;
+ } else {
+ snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
+ btrfs_sb(s)->bdev_holder = fs_type;
+ error = btrfs_fill_super(s, fs_devices, data);
+ }
+ if (error) {
+ deactivate_locked_super(s);
+ goto error_sec_opts;
+ }
+
+ fs_info = btrfs_sb(s);
+ error = setup_security_options(fs_info, s, &new_sec_opts);
+ if (error) {
+ deactivate_locked_super(s);
+ goto error_sec_opts;
+ }
+
+ return dget(s->s_root);
+
+error_close_devices:
+ btrfs_close_devices(fs_devices);
+error_fs_info:
+ free_fs_info(fs_info);
+error_sec_opts:
+ security_free_mnt_opts(&new_sec_opts);
+ return ERR_PTR(error);
+}
/*
* Find a superblock for the given device / mount point.
*
@@ -2133,6 +2240,15 @@ static struct file_system_type btrfs_fs_type = {
.kill_sb = btrfs_kill_super,
.fs_flags = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
};
+
+static struct file_system_type btrfs_root_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "btrfs",
+ .mount = mount_root,
+ .kill_sb = btrfs_kill_super,
+ .fs_flags = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
+};
+
MODULE_ALIAS_FS("btrfs");
static int btrfs_control_open(struct inode *inode, struct file *file)
--
2.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH 1/4] btrfs: add mount_root() and new file_system_type
2017-09-25 7:27 ` [PATCH 1/4] btrfs: add mount_root() and new file_system_type Misono, Tomohiro
@ 2017-12-12 20:07 ` David Sterba
0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2017-12-12 20:07 UTC (permalink / raw)
To: Misono, Tomohiro; +Cc: linux-btrfs, dsterba, anand.jain
On Mon, Sep 25, 2017 at 04:27:07PM +0900, Misono, Tomohiro wrote:
> Add mount_root() and new file_system_type for preparation of cleanup of
> btrfs_mount(). Code path is not changed yet.
>
> mount_root() is almost the same as current btrfs_mount(), but doesn't
> have subvolume related part.
>
> Signed-off-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
> ---
> fs/btrfs/super.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 116 insertions(+)
>
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index 12540b6..fe43606 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -66,6 +66,7 @@
>
> static const struct super_operations btrfs_super_ops;
> static struct file_system_type btrfs_fs_type;
> +static struct file_system_type btrfs_root_fs_type;
A comment why we need this would be useful.
>
> static int btrfs_remount(struct super_block *sb, int *flags, char *data);
>
> @@ -1514,6 +1515,112 @@ static int setup_security_options(struct btrfs_fs_info *fs_info,
> return ret;
> }
>
> +static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
'mount_root' is too generic and could be confused with other mount_*
functions from VFS, btrfs_mount_root would be better.
> + const char *device_name, void *data)
> +{
> + struct block_device *bdev = NULL;
> + struct super_block *s;
> + struct btrfs_fs_devices *fs_devices = NULL;
> + 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 & MS_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);
> + }
> +
> + security_init_mnt_opts(&new_sec_opts);
> + if (data) {
> + error = parse_security_options(data, &new_sec_opts);
> + if (error)
> + 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
> + * it for searching for existing supers, so this lets us do that and
> + * then open_ctree will properly initialize everything later.
> + */
> + fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
Why GFP_NOFS?
> + if (!fs_info) {
> + error = -ENOMEM;
> + goto error_sec_opts;
> + }
> +
> + fs_info->fs_devices = fs_devices;
> +
> + fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
> + fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
Also here. Current code uses GFP_KERNEL so this might got switched in
the meantim.
> + security_init_mnt_opts(&fs_info->security_opts);
> + if (!fs_info->super_copy || !fs_info->super_for_commit) {
> + error = -ENOMEM;
> + goto error_fs_info;
> + }
> +
> + error = btrfs_open_devices(fs_devices, mode, fs_type);
> + if (error)
> + goto error_fs_info;
> +
> + if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
> + error = -EACCES;
> + goto error_close_devices;
> + }
> +
> + bdev = fs_devices->latest_bdev;
> + s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | MS_NOSEC,
> + fs_info);
> + if (IS_ERR(s)) {
> + error = PTR_ERR(s);
> + goto error_close_devices;
> + }
> +
> + if (s->s_root) {
> + btrfs_close_devices(fs_devices);
> + free_fs_info(fs_info);
> + if ((flags ^ s->s_flags) & MS_RDONLY)
> + error = -EBUSY;
> + } else {
> + snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
> + btrfs_sb(s)->bdev_holder = fs_type;
> + error = btrfs_fill_super(s, fs_devices, data);
> + }
> + if (error) {
> + deactivate_locked_super(s);
> + goto error_sec_opts;
> + }
> +
> + fs_info = btrfs_sb(s);
> + error = setup_security_options(fs_info, s, &new_sec_opts);
> + if (error) {
> + deactivate_locked_super(s);
> + goto error_sec_opts;
> + }
> +
> + return dget(s->s_root);
> +
> +error_close_devices:
> + btrfs_close_devices(fs_devices);
> +error_fs_info:
> + free_fs_info(fs_info);
> +error_sec_opts:
> + security_free_mnt_opts(&new_sec_opts);
> + return ERR_PTR(error);
> +}
> /*
> * Find a superblock for the given device / mount point.
> *
> @@ -2133,6 +2240,15 @@ static struct file_system_type btrfs_fs_type = {
> .kill_sb = btrfs_kill_super,
> .fs_flags = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
> };
> +
> +static struct file_system_type btrfs_root_fs_type = {
> + .owner = THIS_MODULE,
> + .name = "btrfs",
> + .mount = mount_root,
> + .kill_sb = btrfs_kill_super,
> + .fs_flags = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
> +};
> +
> MODULE_ALIAS_FS("btrfs");
>
> static int btrfs_control_open(struct inode *inode, struct file *file)
> --
> 2.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/4] btrfs: cleanup btrfs_mount() using mount_root()
2017-09-25 7:26 [PATCH v3 0/4] btrfs: cleanup mount path Misono, Tomohiro
2017-09-25 7:27 ` [PATCH 1/4] btrfs: add mount_root() and new file_system_type Misono, Tomohiro
@ 2017-09-25 7:28 ` Misono, Tomohiro
2017-09-25 7:28 ` [PATCH 3/4] btrfs: split parse_early_options() in two Misono, Tomohiro
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Misono, Tomohiro @ 2017-09-25 7:28 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba, anand.jain
Cleanups btrfs_mount() by using mount_root(). This avoids getting
btrfs_mount() called twice in mount path.
Old btrfs_mount() will do:
0. VFS layer calls vfs_kern_mount() with registered file_system_type
(for btrfs, btrfs_fs_type). btrfs_mount() is called on the way.
1. btrfs_parse_early_options() parses "subvolid=" mount option and set the
value to subvol_objectid. Otherwise, subvol_objectid has the initial
value of 0
2. check subvol_objectid is 5 or not. This time id is not 5, and
btrfs_mount() returns by calling mount_subvol()
3. In mount_subvol(), original mount options are modified to contain
"subvolid=0" in setup_root_args(). Then, vfs_kern_mount() is called with
btrfs_fs_type and new options
4. btrfs_mount() is called again
5. btrfs_parse_early_options() parses "subvolid=0" and set 5 (instead of 0)
to subvol_objectid
6. check subvol_objectid is 5 or not. This time id is 5 and mount_subvol()
is not called. btrfs_mount() finishes mounting a root
7. (in mount_subvol()) with using a return vale of vfs_kern_mount(), it
calls mount_subtree()
8 return subvolume's dentry
Reusing the same file_system_type (and btrfs_mount()) for vfs_kern_mount()
is the cause of complication.
Instead, new btrfs_mount() will do:
1. parse subvol id related options for later use in mount_subvol()
2. mount device's root by calling vfs_kern_mount() with
btrfs_root_fs_type, which is not registered to VFS by
register_filesystem(). As a result, mount_root() is called
3. return by calling mount_subvol()
The code of 2. is moved from the first part of mount_subvol().
Signed-off-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
---
fs/btrfs/super.c | 186 +++++++++++++++++--------------------------------------
1 file changed, 58 insertions(+), 128 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index fe43606..1c34ca6 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1363,48 +1363,11 @@ static char *setup_root_args(char *args)
static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
int flags, const char *device_name,
- char *data)
+ char *data, struct vfsmount *mnt)
{
struct dentry *root;
- struct vfsmount *mnt = NULL;
- char *newargs;
int ret;
- newargs = setup_root_args(data);
- if (!newargs) {
- root = ERR_PTR(-ENOMEM);
- goto out;
- }
-
- mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, newargs);
- if (PTR_ERR_OR_ZERO(mnt) == -EBUSY) {
- if (flags & MS_RDONLY) {
- mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY,
- device_name, newargs);
- } else {
- mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY,
- device_name, newargs);
- if (IS_ERR(mnt)) {
- root = ERR_CAST(mnt);
- mnt = NULL;
- goto out;
- }
-
- down_write(&mnt->mnt_sb->s_umount);
- ret = btrfs_remount(mnt->mnt_sb, &flags, NULL);
- up_write(&mnt->mnt_sb->s_umount);
- if (ret < 0) {
- root = ERR_PTR(ret);
- goto out;
- }
- }
- }
- if (IS_ERR(mnt)) {
- root = ERR_CAST(mnt);
- mnt = NULL;
- goto out;
- }
-
if (!subvol_name) {
if (!subvol_objectid) {
ret = get_default_subvol_objectid(btrfs_sb(mnt->mnt_sb),
@@ -1460,7 +1423,6 @@ static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
out:
mntput(mnt);
- kfree(newargs);
kfree(subvol_name);
return root;
}
@@ -1515,6 +1477,12 @@ static int setup_security_options(struct btrfs_fs_info *fs_info,
return ret;
}
+/*
+ * Find a superblock for the given device / mount point.
+ *
+ * Note: This is based on mount_bdev from fs/super.c with a few additions
+ * for multiple device setup. Make sure to keep it in sync.
+ */
static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
const char *device_name, void *data)
{
@@ -1621,20 +1589,34 @@ static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
security_free_mnt_opts(&new_sec_opts);
return ERR_PTR(error);
}
+
/*
- * Find a superblock for the given device / mount point.
+ * Mount function which is called by VFS layer.
*
- * Note: This is based on get_sb_bdev from fs/super.c with a few additions
- * for multiple device setup. Make sure to keep it in sync.
+ * In order to allow mounting a subvolume directly, btrfs uses
+ * mount_subtree() which needs vfsmount* of device's root (/).
+ * This means device's root has to be mounted internally in any case.
+ *
+ * Operation flow:
+ * 1. Parse subvol id related options for later use in mount_subvol().
+ *
+ * 2. Mount device's root (/) by calling vfs_kern_mount().
+ *
+ * NOTE: vfs_kern_mount() is used by VFS to call btrfs_mount() in the
+ * first place. In order to avoid calling btrfs_mount() again, we use
+ * different file_system_type which is not registered to VFS by
+ * register_filesystem(). As a result, mount_root() is called.
+ * The return value will be used by mount_subtree() in mount_subvol().
+ *
+ * 3. Call mount_subvol() to get the dentry of subvolume. Since there is
+ * "btrfs subvolume set-default", mount_subvol() is called always.
*/
static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
const char *device_name, void *data)
{
- struct block_device *bdev = NULL;
- struct super_block *s;
struct btrfs_fs_devices *fs_devices = NULL;
- struct btrfs_fs_info *fs_info = NULL;
- struct security_mnt_opts new_sec_opts;
+ struct vfsmount *mnt_root;
+ struct dentry *root;
fmode_t mode = FMODE_READ;
char *subvol_name = NULL;
u64 subvol_objectid = 0;
@@ -1651,93 +1633,41 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
return ERR_PTR(error);
}
- if (subvol_name || subvol_objectid != BTRFS_FS_TREE_OBJECTID) {
- /* mount_subvol() will free subvol_name. */
- return mount_subvol(subvol_name, subvol_objectid, flags,
- device_name, data);
- }
-
- security_init_mnt_opts(&new_sec_opts);
- if (data) {
- error = parse_security_options(data, &new_sec_opts);
- if (error)
- 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
- * it for searching for existing supers, so this lets us do that and
- * then open_ctree will properly initialize everything later.
- */
- fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
- if (!fs_info) {
- error = -ENOMEM;
- goto error_sec_opts;
- }
-
- fs_info->fs_devices = fs_devices;
-
- fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
- fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
- security_init_mnt_opts(&fs_info->security_opts);
- if (!fs_info->super_copy || !fs_info->super_for_commit) {
- error = -ENOMEM;
- goto error_fs_info;
- }
-
- error = btrfs_open_devices(fs_devices, mode, fs_type);
- if (error)
- goto error_fs_info;
-
- if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
- error = -EACCES;
- goto error_close_devices;
- }
-
- bdev = fs_devices->latest_bdev;
- s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | MS_NOSEC,
- fs_info);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto error_close_devices;
- }
+ /* mount device's root (/) */
+ mnt_root = vfs_kern_mount(&btrfs_root_fs_type, flags, device_name, data);
+ if (PTR_ERR_OR_ZERO(mnt_root) == -EBUSY) {
+ if (flags & MS_RDONLY) {
+ mnt_root = vfs_kern_mount(&btrfs_root_fs_type, flags & ~MS_RDONLY,
+ device_name, data);
+ } else {
+ mnt_root = vfs_kern_mount(&btrfs_root_fs_type, flags | MS_RDONLY,
+ device_name, data);
+ if (IS_ERR(mnt_root)) {
+ root = ERR_CAST(mnt_root);
+ goto out;
+ }
- if (s->s_root) {
- btrfs_close_devices(fs_devices);
- free_fs_info(fs_info);
- if ((flags ^ s->s_flags) & MS_RDONLY)
- error = -EBUSY;
- } else {
- snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
- btrfs_sb(s)->bdev_holder = fs_type;
- error = btrfs_fill_super(s, fs_devices, data);
- }
- if (error) {
- deactivate_locked_super(s);
- goto error_sec_opts;
+ down_write(&mnt_root->mnt_sb->s_umount);
+ error = btrfs_remount(mnt_root->mnt_sb, &flags, NULL);
+ up_write(&mnt_root->mnt_sb->s_umount);
+ if (error < 0) {
+ root = ERR_PTR(error);
+ mntput(mnt_root);
+ goto out;
+ }
+ }
}
-
- fs_info = btrfs_sb(s);
- error = setup_security_options(fs_info, s, &new_sec_opts);
- if (error) {
- deactivate_locked_super(s);
- goto error_sec_opts;
+ if (IS_ERR(mnt_root)) {
+ root = ERR_CAST(mnt_root);
+ goto out;
}
- return dget(s->s_root);
+ /* mount_subvol() will free subvol_name and mnt_root */
+ root = mount_subvol(subvol_name, subvol_objectid, flags,
+ device_name, data, mnt_root);
-error_close_devices:
- btrfs_close_devices(fs_devices);
-error_fs_info:
- free_fs_info(fs_info);
-error_sec_opts:
- security_free_mnt_opts(&new_sec_opts);
- return ERR_PTR(error);
+out:
+ return root;
}
static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
--
2.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH 3/4] btrfs: split parse_early_options() in two
2017-09-25 7:26 [PATCH v3 0/4] btrfs: cleanup mount path Misono, Tomohiro
2017-09-25 7:27 ` [PATCH 1/4] btrfs: add mount_root() and new file_system_type Misono, Tomohiro
2017-09-25 7:28 ` [PATCH 2/4] btrfs: cleanup btrfs_mount() using mount_root() Misono, Tomohiro
@ 2017-09-25 7:28 ` Misono, Tomohiro
2017-12-12 20:10 ` David Sterba
2017-09-25 7:29 ` [PATCH 4/4] btrfs: remove unused setup_root_args() Misono, Tomohiro
2017-10-16 15:15 ` [PATCH v3 0/4] btrfs: cleanup mount path David Sterba
4 siblings, 1 reply; 9+ messages in thread
From: Misono, Tomohiro @ 2017-09-25 7:28 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba, anand.jain
Now parse_early_options() is used by both btrfs_mount() and 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>
---
fs/btrfs/super.c | 85 +++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 60 insertions(+), 25 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 1c34ca6..7edd74d 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -448,7 +448,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;
@@ -855,11 +856,63 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
* 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);
+ switch (token) {
+ 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;
+ }
+ }
+
+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;
@@ -867,8 +920,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)
@@ -907,18 +960,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;
}
@@ -1492,18 +1533,14 @@ static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
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 & MS_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);
}
@@ -1614,7 +1651,6 @@ static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
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;
@@ -1625,9 +1661,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
if (!(flags & MS_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);
--
2.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH 3/4] btrfs: split parse_early_options() in two
2017-09-25 7:28 ` [PATCH 3/4] btrfs: split parse_early_options() in two Misono, Tomohiro
@ 2017-12-12 20:10 ` David Sterba
0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2017-12-12 20:10 UTC (permalink / raw)
To: Misono, Tomohiro; +Cc: linux-btrfs, dsterba, anand.jain
On Mon, Sep 25, 2017 at 04:28:36PM +0900, Misono, Tomohiro wrote:
> Now parse_early_options() is used by both btrfs_mount() and 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>
> ---
> fs/btrfs/super.c | 85 +++++++++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 60 insertions(+), 25 deletions(-)
>
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index 1c34ca6..7edd74d 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -448,7 +448,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;
> @@ -855,11 +856,63 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
> * 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);
> + switch (token) {
> + case Opt_device:
Please rewrite this as a simple 'if'.
> + 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;
> + }
> + }
> +
> +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;
>
> @@ -867,8 +920,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)
> @@ -907,18 +960,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;
> }
> @@ -1492,18 +1533,14 @@ static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
> 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 & MS_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);
> }
>
> @@ -1614,7 +1651,6 @@ static struct dentry *mount_root(struct file_system_type *fs_type, int flags,
> 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;
> @@ -1625,9 +1661,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
> if (!(flags & MS_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);
> --
> 2.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] btrfs: remove unused setup_root_args()
2017-09-25 7:26 [PATCH v3 0/4] btrfs: cleanup mount path Misono, Tomohiro
` (2 preceding siblings ...)
2017-09-25 7:28 ` [PATCH 3/4] btrfs: split parse_early_options() in two Misono, Tomohiro
@ 2017-09-25 7:29 ` Misono, Tomohiro
2017-10-16 15:15 ` [PATCH v3 0/4] btrfs: cleanup mount path David Sterba
4 siblings, 0 replies; 9+ messages in thread
From: Misono, Tomohiro @ 2017-09-25 7:29 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba, anand.jain
Since setup_root_args() is not used anymore, just remove it.
Signed-off-by: Tomohiro Misono <misono.tomohiro@jp.fujitsu.com>
---
fs/btrfs/super.c | 35 -----------------------------------
1 file changed, 35 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 7edd74d..f589c5b 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1367,41 +1367,6 @@ static inline int is_subvolume_inode(struct inode *inode)
return 0;
}
-/*
- * This will add subvolid=0 to the argument string while removing any subvol=
- * and subvolid= arguments to make sure we get the top-level root for path
- * walking to the subvol we want.
- */
-static char *setup_root_args(char *args)
-{
- char *buf, *dst, *sep;
-
- if (!args)
- return kstrdup("subvolid=0", GFP_NOFS);
-
- /* The worst case is that we add ",subvolid=0" to the end. */
- buf = dst = kmalloc(strlen(args) + strlen(",subvolid=0") + 1, GFP_NOFS);
- if (!buf)
- return NULL;
-
- while (1) {
- sep = strchrnul(args, ',');
- if (!strstarts(args, "subvol=") &&
- !strstarts(args, "subvolid=")) {
- memcpy(dst, args, sep - args);
- dst += sep - args;
- *dst++ = ',';
- }
- if (*sep)
- args = sep + 1;
- else
- break;
- }
- strcpy(dst, "subvolid=0");
-
- return buf;
-}
-
static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
int flags, const char *device_name,
char *data, struct vfsmount *mnt)
--
2.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v3 0/4] btrfs: cleanup mount path
2017-09-25 7:26 [PATCH v3 0/4] btrfs: cleanup mount path Misono, Tomohiro
` (3 preceding siblings ...)
2017-09-25 7:29 ` [PATCH 4/4] btrfs: remove unused setup_root_args() Misono, Tomohiro
@ 2017-10-16 15:15 ` David Sterba
2017-12-12 20:12 ` David Sterba
4 siblings, 1 reply; 9+ messages in thread
From: David Sterba @ 2017-10-16 15:15 UTC (permalink / raw)
To: Misono, Tomohiro; +Cc: linux-btrfs, dsterba, anand.jain
On Mon, Sep 25, 2017 at 04:26:30PM +0900, Misono, Tomohiro wrote:
> Summary:
> Cleanup mount path by avoiding calling btrfs_mount() twice.
> No functional change. See below for longer explanation.
>
> Changelog:
> v3:
> Reorganized patches again into four and added comments to the source.
> Each patch can be applied and compiled while maintaining functionality.
> The first one is the preparation and the second one is the main part.
> The last two are small cleanups.
I'm conditionally adding this series to for-next for testing.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v3 0/4] btrfs: cleanup mount path
2017-10-16 15:15 ` [PATCH v3 0/4] btrfs: cleanup mount path David Sterba
@ 2017-12-12 20:12 ` David Sterba
0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2017-12-12 20:12 UTC (permalink / raw)
To: dsterba, Misono, Tomohiro, linux-btrfs, anand.jain
On Mon, Oct 16, 2017 at 05:15:38PM +0200, David Sterba wrote:
> On Mon, Sep 25, 2017 at 04:26:30PM +0900, Misono, Tomohiro wrote:
> > Summary:
> > Cleanup mount path by avoiding calling btrfs_mount() twice.
> > No functional change. See below for longer explanation.
> >
> > Changelog:
> > v3:
> > Reorganized patches again into four and added comments to the source.
> > Each patch can be applied and compiled while maintaining functionality.
> > The first one is the preparation and the second one is the main part.
> > The last two are small cleanups.
>
> I'm conditionally adding this series to for-next for testing.
No problems while this patch has been in for-next, so I'm going to add
that to 4.16 queue. Please update the patchset according to my comments.
Also please review if there's anything relevant for th MS_* and SB_*
rename that happened in 4.15 (1751e8a6cb935). Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread