diff options
author | root <root@artemis.panaceas.org> | 2015-12-25 04:40:36 +0000 |
---|---|---|
committer | root <root@artemis.panaceas.org> | 2015-12-25 04:40:36 +0000 |
commit | 849369d6c66d3054688672f97d31fceb8e8230fb (patch) | |
tree | 6135abc790ca67dedbe07c39806591e70eda81ce /fs/nfsctl.c | |
download | linux-3.0.35-kobo-849369d6c66d3054688672f97d31fceb8e8230fb.tar.gz linux-3.0.35-kobo-849369d6c66d3054688672f97d31fceb8e8230fb.tar.bz2 linux-3.0.35-kobo-849369d6c66d3054688672f97d31fceb8e8230fb.zip |
initial_commit
Diffstat (limited to 'fs/nfsctl.c')
-rw-r--r-- | fs/nfsctl.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/fs/nfsctl.c b/fs/nfsctl.c new file mode 100644 index 00000000..124e8fcb --- /dev/null +++ b/fs/nfsctl.c @@ -0,0 +1,100 @@ +/* + * fs/nfsctl.c + * + * This should eventually move to userland. + * + */ +#include <linux/types.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/nfsd/syscall.h> +#include <linux/cred.h> +#include <linux/sched.h> +#include <linux/linkage.h> +#include <linux/namei.h> +#include <linux/mount.h> +#include <linux/syscalls.h> +#include <asm/uaccess.h> + +/* + * open a file on nfsd fs + */ + +static struct file *do_open(char *name, int flags) +{ + struct vfsmount *mnt; + struct file *file; + + mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); + if (IS_ERR(mnt)) + return (struct file *)mnt; + + file = file_open_root(mnt->mnt_root, mnt, name, flags); + + mntput(mnt); /* drop do_kern_mount reference */ + return file; +} + +static struct { + char *name; int wsize; int rsize; +} map[] = { + [NFSCTL_SVC] = { + .name = ".svc", + .wsize = sizeof(struct nfsctl_svc) + }, + [NFSCTL_ADDCLIENT] = { + .name = ".add", + .wsize = sizeof(struct nfsctl_client) + }, + [NFSCTL_DELCLIENT] = { + .name = ".del", + .wsize = sizeof(struct nfsctl_client) + }, + [NFSCTL_EXPORT] = { + .name = ".export", + .wsize = sizeof(struct nfsctl_export) + }, + [NFSCTL_UNEXPORT] = { + .name = ".unexport", + .wsize = sizeof(struct nfsctl_export) + }, + [NFSCTL_GETFD] = { + .name = ".getfd", + .wsize = sizeof(struct nfsctl_fdparm), + .rsize = NFS_FHSIZE + }, + [NFSCTL_GETFS] = { + .name = ".getfs", + .wsize = sizeof(struct nfsctl_fsparm), + .rsize = sizeof(struct knfsd_fh) + }, +}; + +SYSCALL_DEFINE3(nfsservctl, int, cmd, struct nfsctl_arg __user *, arg, + void __user *, res) +{ + struct file *file; + void __user *p = &arg->u; + int version; + int err; + + if (copy_from_user(&version, &arg->ca_version, sizeof(int))) + return -EFAULT; + + if (version != NFSCTL_VERSION) + return -EINVAL; + + if (cmd < 0 || cmd >= ARRAY_SIZE(map) || !map[cmd].name) + return -EINVAL; + + file = do_open(map[cmd].name, map[cmd].rsize ? O_RDWR : O_WRONLY); + if (IS_ERR(file)) + return PTR_ERR(file); + err = file->f_op->write(file, p, map[cmd].wsize, &file->f_pos); + if (err >= 0 && map[cmd].rsize) + err = file->f_op->read(file, res, map[cmd].rsize, &file->f_pos); + if (err >= 0) + err = 0; + fput(file); + return err; +} |