Commit d2e0981c authored by David Howells's avatar David Howells Committed by Al Viro

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: default avatarDavid 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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8f8d8d11
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -20,7 +22,6 @@ ...@@ -20,7 +22,6 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/parser.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/spu.h> #include <asm/spu.h>
...@@ -30,7 +31,7 @@ ...@@ -30,7 +31,7 @@
#include "spufs.h" #include "spufs.h"
struct spufs_sb_info { struct spufs_sb_info {
int debug; bool debug;
}; };
static struct kmem_cache *spufs_inode_cache; static struct kmem_cache *spufs_inode_cache;
...@@ -574,16 +575,27 @@ long spufs_create(struct path *path, struct dentry *dentry, ...@@ -574,16 +575,27 @@ long spufs_create(struct path *path, struct dentry *dentry,
} }
/* File system initialization */ /* File system initialization */
struct spufs_fs_context {
kuid_t uid;
kgid_t gid;
umode_t mode;
};
enum { 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 = { static const struct fs_parameter_description spufs_fs_parameters = {
{ Opt_uid, "uid=%d" }, .name = "spufs",
{ Opt_gid, "gid=%d" }, .specs = spufs_param_specs,
{ Opt_mode, "mode=%o" },
{ Opt_debug, "debug" },
{ Opt_err, NULL },
}; };
static int spufs_show_options(struct seq_file *m, struct dentry *root) 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) ...@@ -604,47 +616,41 @@ static int spufs_show_options(struct seq_file *m, struct dentry *root)
return 0; return 0;
} }
static int static int spufs_parse_param(struct fs_context *fc, struct fs_parameter *param)
spufs_parse_options(struct super_block *sb, char *options, struct inode *root) {
{ struct spufs_fs_context *ctx = fc->fs_private;
char *p; struct spufs_sb_info *sbi = fc->s_fs_info;
substring_t args[MAX_OPT_ARGS]; struct fs_parse_result result;
kuid_t uid;
while ((p = strsep(&options, ",")) != NULL) { kgid_t gid;
int token, option; int opt;
if (!*p) opt = fs_parse(fc, &spufs_fs_parameters, param, &result);
continue; if (opt < 0)
return opt;
token = match_token(p, spufs_tokens, args);
switch (token) { switch (opt) {
case Opt_uid: case Opt_uid:
if (match_int(&args[0], &option)) uid = make_kuid(current_user_ns(), result.uint_32);
return 0; if (!uid_valid(uid))
root->i_uid = make_kuid(current_user_ns(), option); return invalf(fc, "Unknown uid");
if (!uid_valid(root->i_uid)) ctx->uid = uid;
return 0; break;
break; case Opt_gid:
case Opt_gid: gid = make_kgid(current_user_ns(), result.uint_32);
if (match_int(&args[0], &option)) if (!gid_valid(gid))
return 0; return invalf(fc, "Unknown gid");
root->i_gid = make_kgid(current_user_ns(), option); ctx->gid = gid;
if (!gid_valid(root->i_gid)) break;
return 0; case Opt_mode:
break; ctx->mode = result.uint_32 & S_IALLUGO;
case Opt_mode: break;
if (match_octal(&args[0], &option)) case Opt_debug:
return 0; sbi->debug = true;
root->i_mode = option | S_IFDIR; break;
break;
case Opt_debug:
spufs_get_sb_info(sb)->debug = 1;
break;
default:
return 0;
}
} }
return 1;
return 0;
} }
static void spufs_exit_isolated_loader(void) static void spufs_exit_isolated_loader(void)
...@@ -678,79 +684,98 @@ spufs_init_isolated_loader(void) ...@@ -678,79 +684,98 @@ spufs_init_isolated_loader(void)
printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
} }
static int static int spufs_create_root(struct super_block *sb, struct fs_context *fc)
spufs_create_root(struct super_block *sb, void *data)
{ {
struct spufs_fs_context *ctx = fc->fs_private;
struct inode *inode; struct inode *inode;
int ret;
ret = -ENODEV;
if (!spu_management_ops) if (!spu_management_ops)
goto out; return -ENODEV;
ret = -ENOMEM; inode = spufs_new_inode(sb, S_IFDIR | ctx->mode);
inode = spufs_new_inode(sb, S_IFDIR | 0775);
if (!inode) 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_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
SPUFS_I(inode)->i_ctx = NULL; SPUFS_I(inode)->i_ctx = NULL;
inc_nlink(inode); inc_nlink(inode);
ret = -EINVAL;
if (!spufs_parse_options(sb, data, inode))
goto out_iput;
ret = -ENOMEM;
sb->s_root = d_make_root(inode); sb->s_root = d_make_root(inode);
if (!sb->s_root) if (!sb->s_root)
goto out; return -ENOMEM;
return 0; return 0;
out_iput:
iput(inode);
out:
return ret;
} }
static int static const struct super_operations spufs_ops = {
spufs_fill_super(struct super_block *sb, void *data, int silent) .alloc_inode = spufs_alloc_inode,
{ .free_inode = spufs_free_inode,
struct spufs_sb_info *info; .statfs = simple_statfs,
static const struct super_operations s_ops = { .evict_inode = spufs_evict_inode,
.alloc_inode = spufs_alloc_inode, .show_options = spufs_show_options,
.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 int spufs_fill_super(struct super_block *sb, struct fs_context *fc)
{
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_SIZE; sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT; sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = SPUFS_MAGIC; sb->s_magic = SPUFS_MAGIC;
sb->s_op = &s_ops; sb->s_op = &spufs_ops;
sb->s_fs_info = info;
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 * static void spufs_free_fc(struct fs_context *fc)
spufs_mount(struct file_system_type *fstype, int flags,
const char *name, void *data)
{ {
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 = { static struct file_system_type spufs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "spufs", .name = "spufs",
.mount = spufs_mount, .init_fs_context = spufs_init_fs_context,
.parameters = &spufs_fs_parameters,
.kill_sb = kill_litter_super, .kill_sb = kill_litter_super,
}; };
MODULE_ALIAS_FS("spufs"); MODULE_ALIAS_FS("spufs");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment