From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- fs/nfsctl.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 fs/nfsctl.c (limited to 'fs/nfsctl.c') diff --git a/fs/nfsctl.c b/fs/nfsctl.c new file mode 100644 index 0000000..0b14938 --- /dev/null +++ b/fs/nfsctl.c @@ -0,0 +1,118 @@ +/* + * fs/nfsctl.c + * + * This should eventually move to userland. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * open a file on nfsd fs + */ + +static struct file *do_open(char *name, int flags) +{ + struct nameidata nd; + int error; + + nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); + + if (IS_ERR(nd.mnt)) + return (struct file *)nd.mnt; + + nd.dentry = dget(nd.mnt->mnt_root); + nd.last_type = LAST_ROOT; + nd.flags = 0; + nd.depth = 0; + + error = path_walk(name, &nd); + if (error) + return ERR_PTR(error); + + if (flags == O_RDWR) + error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE); + else + error = may_open(&nd, MAY_WRITE, FMODE_WRITE); + + if (!error) + return dentry_open(nd.dentry, nd.mnt, flags); + + path_release(&nd); + return ERR_PTR(error); +} + +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) + }, +}; + +long +asmlinkage sys_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) { + printk(KERN_WARNING "nfsd: incompatible version in syscall.\n"); + return -EINVAL; + } + + if (cmd < 0 || cmd >= sizeof(map)/sizeof(map[0]) || !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; +} -- cgit v1.1