Skip to content

Commit

Permalink
vfs: Convert spufs to use the new mount API
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Howells authored and Al Viro committed Sep 19, 2019
1 parent 8f8d8d1 commit d2e0981
Showing 1 changed file with 116 additions and 91 deletions.
207 changes: 116 additions & 91 deletions arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand All @@ -30,7 +31,7 @@
#include "spufs.h"

struct spufs_sb_info {
int debug;
bool debug;
};

static struct kmem_cache *spufs_inode_cache;
Expand Down Expand Up @@ -574,16 +575,27 @@ long spufs_create(struct path *path, struct dentry *dentry,
}

/* File system initialization */
struct spufs_fs_context {
kuid_t uid;
kgid_t gid;
umode_t mode;
};

enum {
Opt_uid, Opt_gid, Opt_mode, Opt_debug, Opt_err,
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 match_table_t spufs_tokens = {
{ Opt_uid, "uid=%d" },
{ Opt_gid, "gid=%d" },
{ Opt_mode, "mode=%o" },
{ Opt_debug, "debug" },
{ Opt_err, NULL },
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)
Expand All @@ -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)
{
char *p;
substring_t args[MAX_OPT_ARGS];

while ((p = strsep(&options, ",")) != NULL) {
int token, option;

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;
}
static int spufs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
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;

opt = fs_parse(fc, &spufs_fs_parameters, param, &result);
if (opt < 0)
return opt;

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)
Expand Down Expand Up @@ -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)
{
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;
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)
{
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 int spufs_get_tree(struct fs_context *fc)
{
return get_tree_single(fc, spufs_fill_super);
}

static struct dentry *
spufs_mount(struct file_system_type *fstype, int flags,
const char *name, void *data)
static void spufs_free_fc(struct fs_context *fc)
{
return mount_single(fstype, flags, data, spufs_fill_super);
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");
Expand Down

0 comments on commit d2e0981

Please sign in to comment.