Commit 063b009f authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] nfsd as filesystem

* introduces a new filesystem - nfsd.  No, it's not a typo.  It's a small
  tree with fixed topology defined by nfsd and IO on its files does what
  we used to do by hand in nfsctl.c.
* turns sys_nfsservctl() into a sequence of open()/write()/read()/close()
  It works as it used to - we don't need nfsd to be mounted anywhere, etc.
* nfsd_linkage ugliness is gone.
* getfs and getfh demonstrate (rather trivial) example of "descriptor as
  transaction descriptor" behaviour.
* we are fairly close to the situation when driver-defined filesystems can
  be done with practically zero code overhead.  We are still not there, but
  it's a matter of adding a couple of helpers for populating the tree.

	One thing we get immediately is a cleanup of sys_nfsservctl() -
it got _much_ better.  Moreover, we get an alternative interface that
uses normal file IO and can be used without magic syscalls.
parent edb1bea5
......@@ -22,6 +22,12 @@ else
obj-y += noquot.o
endif
ifneq ($(CONFIG_NFSD),n)
ifneq ($(CONFIG_NFSD),)
obj-y += nfsctl.o
endif
endif
subdir-$(CONFIG_PROC_FS) += proc
subdir-y += partitions
subdir-y += driverfs
......
......@@ -1252,6 +1252,7 @@ kmem_cache_t *dquot_cachep;
/* SLAB cache for buffer_head structures */
kmem_cache_t *bh_cachep;
EXPORT_SYMBOL(bh_cachep);
EXPORT_SYMBOL(d_genocide);
extern void bdev_cache_init(void);
extern void cdev_cache_init(void);
......
......@@ -3,39 +3,10 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* nfsservctl system-call when nfsd is not compiled in.
* table of configured filesystems
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/smp_lock.h>
#include <linux/kmod.h>
#include <linux/nfsd/interface.h>
#include <linux/linkage.h>
#if ! defined(CONFIG_NFSD)
struct nfsd_linkage *nfsd_linkage;
long
asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp)
{
int ret = -ENOSYS;
#if defined(CONFIG_MODULES)
lock_kernel();
if (nfsd_linkage ||
(request_module ("nfsd") == 0 && nfsd_linkage)) {
__MOD_INC_USE_COUNT(nfsd_linkage->owner);
unlock_kernel();
ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp);
__MOD_DEC_USE_COUNT(nfsd_linkage->owner);
} else
unlock_kernel();
#endif
return ret;
}
EXPORT_SYMBOL(nfsd_linkage);
#endif /* CONFIG_NFSD */
/*
* Code will move here from fs/super.c and yes, it will be fs type handling
* stuff.
*/
/*
* fs/nfsctl.c
*
* This should eventually move to userland.
*
*/
#include <linux/config.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/syscall.h>
#include <linux/linkage.h>
#include <asm/uaccess.h>
/*
* open a file on nfsd fs
*/
struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
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;
error = path_walk(name, &nd);
if (error)
return ERR_PTR(error);
return dentry_open(nd.dentry, nd.mnt, flags);
}
static struct {
char *name; int wsize; int rsize;
} map[] = {
[NFSCTL_SVC]={"svc", sizeof(struct nfsctl_svc)},
[NFSCTL_ADDCLIENT]={"add", sizeof(struct nfsctl_client)},
[NFSCTL_DELCLIENT]={"del", sizeof(struct nfsctl_client)},
[NFSCTL_EXPORT]={"export", sizeof(struct nfsctl_export)},
[NFSCTL_UNEXPORT]={"unexport", sizeof(struct nfsctl_export)},
#ifdef notyet
[NFSCTL_UGIDUPDATE]={"ugid", sizeof(struct nfsctl_uidmap)},
#endif
[NFSCTL_GETFD]={"getfd", sizeof(struct nfsctl_fdparm), NFS_FHSIZE},
[NFSCTL_GETFS]={"getfs", sizeof(struct nfsctl_fsparm), sizeof(struct knfsd_fh)},
};
long
asmlinkage sys_nfsservctl(int cmd, struct nfsctl_arg *arg, void *res)
{
struct file *file;
void *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;
}
This diff is collapsed.
......@@ -10,17 +10,4 @@
#ifndef LINUX_NFSD_INTERFACE_H
#define LINUX_NFSD_INTERFACE_H
#include <linux/config.h>
#ifndef CONFIG_NFSD
#ifdef CONFIG_MODULES
extern struct nfsd_linkage {
long (*do_nfsservctl)(int cmd, void *argp, void *resp);
struct module *owner;
} * nfsd_linkage;
#endif
#endif
#endif /* LINUX_NFSD_INTERFACE_H */
......@@ -133,7 +133,7 @@ union nfsctl_res {
* Kernel syscall implementation.
*/
#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
extern asmlinkage long sys_nfsservctl(int, void *, void *);
extern asmlinkage long sys_nfsservctl(int, struct nfsctl_arg *, void *);
#else
#define sys_nfsservctl sys_ni_syscall
#endif
......
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