vfs: Convert spufs to use the new mount API

Convert the spufs filesystem to the new internal mount API as the old
one will be obsoleted and removed.  This allows greater flexibility in
communication of mount parameters between userspace, the VFS and the
filesystem.

See Documentation/filesystems/mount_api.txt for more information.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jeremy Kerr <jk@ozlabs.org>
cc: Arnd Bergmann <arnd@arndb.de>
cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
David Howells 2019-03-21 10:34:14 +00:00 committed by Al Viro
parent 8f8d8d11f7
commit d2e0981c3b

View File

@ -10,6 +10,8 @@
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include <linux/fsnotify.h>
#include <linux/backing-dev.h>
#include <linux/init.h>
@ -20,7 +22,6 @@
#include <linux/pagemap.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/parser.h>
#include <asm/prom.h>
#include <asm/spu.h>
@ -30,7 +31,7 @@
#include "spufs.h"
struct spufs_sb_info {
int debug;
bool debug;
};
static struct kmem_cache *spufs_inode_cache;
@ -574,16 +575,27 @@ long spufs_create(struct path *path, struct dentry *dentry,
}
/* File system initialization */
enum {
Opt_uid, Opt_gid, Opt_mode, Opt_debug, Opt_err,
struct spufs_fs_context {
kuid_t uid;
kgid_t gid;
umode_t mode;
};
static const match_table_t spufs_tokens = {
{ Opt_uid, "uid=%d" },
{ Opt_gid, "gid=%d" },
{ Opt_mode, "mode=%o" },
{ Opt_debug, "debug" },
{ Opt_err, NULL },
enum {
Opt_uid, Opt_gid, Opt_mode, Opt_debug,
};
static const struct fs_parameter_spec spufs_param_specs[] = {
fsparam_u32 ("gid", Opt_gid),
fsparam_u32oct ("mode", Opt_mode),
fsparam_u32 ("uid", Opt_uid),
fsparam_flag ("debug", Opt_debug),
{}
};
static const struct fs_parameter_description spufs_fs_parameters = {
.name = "spufs",
.specs = spufs_param_specs,
};
static int spufs_show_options(struct seq_file *m, struct dentry *root)
@ -604,47 +616,41 @@ static int spufs_show_options(struct seq_file *m, struct dentry *root)
return 0;
}
static int
spufs_parse_options(struct super_block *sb, char *options, struct inode *root)
static int spufs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
char *p;
substring_t args[MAX_OPT_ARGS];
struct spufs_fs_context *ctx = fc->fs_private;
struct spufs_sb_info *sbi = fc->s_fs_info;
struct fs_parse_result result;
kuid_t uid;
kgid_t gid;
int opt;
while ((p = strsep(&options, ",")) != NULL) {
int token, option;
opt = fs_parse(fc, &spufs_fs_parameters, param, &result);
if (opt < 0)
return opt;
if (!*p)
continue;
token = match_token(p, spufs_tokens, args);
switch (token) {
case Opt_uid:
if (match_int(&args[0], &option))
return 0;
root->i_uid = make_kuid(current_user_ns(), option);
if (!uid_valid(root->i_uid))
return 0;
break;
case Opt_gid:
if (match_int(&args[0], &option))
return 0;
root->i_gid = make_kgid(current_user_ns(), option);
if (!gid_valid(root->i_gid))
return 0;
break;
case Opt_mode:
if (match_octal(&args[0], &option))
return 0;
root->i_mode = option | S_IFDIR;
break;
case Opt_debug:
spufs_get_sb_info(sb)->debug = 1;
break;
default:
return 0;
}
switch (opt) {
case Opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return invalf(fc, "Unknown uid");
ctx->uid = uid;
break;
case Opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return invalf(fc, "Unknown gid");
ctx->gid = gid;
break;
case Opt_mode:
ctx->mode = result.uint_32 & S_IALLUGO;
break;
case Opt_debug:
sbi->debug = true;
break;
}
return 1;
return 0;
}
static void spufs_exit_isolated_loader(void)
@ -678,79 +684,98 @@ spufs_init_isolated_loader(void)
printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
}
static int
spufs_create_root(struct super_block *sb, void *data)
static int spufs_create_root(struct super_block *sb, struct fs_context *fc)
{
struct spufs_fs_context *ctx = fc->fs_private;
struct inode *inode;
int ret;
ret = -ENODEV;
if (!spu_management_ops)
goto out;
return -ENODEV;
ret = -ENOMEM;
inode = spufs_new_inode(sb, S_IFDIR | 0775);
inode = spufs_new_inode(sb, S_IFDIR | ctx->mode);
if (!inode)
goto out;
return -ENOMEM;
inode->i_uid = ctx->uid;
inode->i_gid = ctx->gid;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
SPUFS_I(inode)->i_ctx = NULL;
inc_nlink(inode);
ret = -EINVAL;
if (!spufs_parse_options(sb, data, inode))
goto out_iput;
ret = -ENOMEM;
sb->s_root = d_make_root(inode);
if (!sb->s_root)
goto out;
return -ENOMEM;
return 0;
out_iput:
iput(inode);
out:
return ret;
}
static int
spufs_fill_super(struct super_block *sb, void *data, int silent)
static const struct super_operations spufs_ops = {
.alloc_inode = spufs_alloc_inode,
.free_inode = spufs_free_inode,
.statfs = simple_statfs,
.evict_inode = spufs_evict_inode,
.show_options = spufs_show_options,
};
static int spufs_fill_super(struct super_block *sb, struct fs_context *fc)
{
struct spufs_sb_info *info;
static const struct super_operations s_ops = {
.alloc_inode = spufs_alloc_inode,
.free_inode = spufs_free_inode,
.statfs = simple_statfs,
.evict_inode = spufs_evict_inode,
.show_options = spufs_show_options,
};
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = SPUFS_MAGIC;
sb->s_op = &s_ops;
sb->s_fs_info = info;
sb->s_op = &spufs_ops;
return spufs_create_root(sb, data);
return spufs_create_root(sb, fc);
}
static struct dentry *
spufs_mount(struct file_system_type *fstype, int flags,
const char *name, void *data)
static int spufs_get_tree(struct fs_context *fc)
{
return mount_single(fstype, flags, data, spufs_fill_super);
return get_tree_single(fc, spufs_fill_super);
}
static void spufs_free_fc(struct fs_context *fc)
{
kfree(fc->s_fs_info);
}
static const struct fs_context_operations spufs_context_ops = {
.free = spufs_free_fc,
.parse_param = spufs_parse_param,
.get_tree = spufs_get_tree,
};
static int spufs_init_fs_context(struct fs_context *fc)
{
struct spufs_fs_context *ctx;
struct spufs_sb_info *sbi;
ctx = kzalloc(sizeof(struct spufs_fs_context), GFP_KERNEL);
if (!ctx)
goto nomem;
sbi = kzalloc(sizeof(struct spufs_sb_info), GFP_KERNEL);
if (!sbi)
goto nomem_ctx;
ctx->uid = current_uid();
ctx->gid = current_gid();
ctx->mode = 0755;
fc->s_fs_info = sbi;
fc->ops = &spufs_context_ops;
return 0;
nomem_ctx:
kfree(ctx);
nomem:
return -ENOMEM;
}
static struct file_system_type spufs_type = {
.owner = THIS_MODULE,
.name = "spufs",
.mount = spufs_mount,
.init_fs_context = spufs_init_fs_context,
.parameters = &spufs_fs_parameters,
.kill_sb = kill_litter_super,
};
MODULE_ALIAS_FS("spufs");