fuse: add dedicated filesystem context ops for submounts

The creation of a submount is open-coded in fuse_dentry_automount().
This brings a lot of complexity and we recently had to fix bugs
because we weren't setting SB_BORN or because we were unlocking
sb->s_umount before sb was fully configured. Most of these could
have been avoided by using the mount API instead of open-coding.

Basically, this means coming up with a proper ->get_tree()
implementation for submounts and call vfs_get_tree(), or better
fc_mount().

The creation of the superblock for submounts is quite different from
the root mount. Especially, it doesn't require to allocate a FUSE
filesystem context, nor to parse parameters.

Introduce a dedicated context ops for submounts to make this clear.
This is just a placeholder for now, fuse_get_tree_submount() will
be populated in a subsequent patch.

Only visible change is that we stop allocating/freeing a useless FUSE
filesystem context with submounts.

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Greg Kurz 2021-06-04 18:11:53 +02:00 committed by Miklos Szeredi
parent 2d82ab251e
commit fe0a7bd81b
3 changed files with 24 additions and 0 deletions

View file

@ -1100,6 +1100,11 @@ int fuse_fill_super_submount(struct super_block *sb,
*/
bool fuse_mount_remove(struct fuse_mount *fm);
/*
* Setup context ops for submounts
*/
int fuse_init_fs_context_submount(struct fs_context *fsc);
/*
* Shut down the connection (possibly sending DESTROY request).
*/

View file

@ -1353,6 +1353,22 @@ int fuse_fill_super_submount(struct super_block *sb,
return 0;
}
static int fuse_get_tree_submount(struct fs_context *fsc)
{
return 0;
}
static const struct fs_context_operations fuse_context_submount_ops = {
.get_tree = fuse_get_tree_submount,
};
int fuse_init_fs_context_submount(struct fs_context *fsc)
{
fsc->ops = &fuse_context_submount_ops;
return 0;
}
EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount);
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
{
struct fuse_dev *fud = NULL;

View file

@ -1497,6 +1497,9 @@ static int virtio_fs_init_fs_context(struct fs_context *fsc)
{
struct fuse_fs_context *ctx;
if (fsc->purpose == FS_CONTEXT_FOR_SUBMOUNT)
return fuse_init_fs_context_submount(fsc);
ctx = kzalloc(sizeof(struct fuse_fs_context), GFP_KERNEL);
if (!ctx)
return -ENOMEM;