Commit 49b28684 authored by NeilBrown's avatar NeilBrown Committed by J. Bruce Fields

nfsd: Remove deprecated nfsctl system call and related code.

As promised in feature-removal-schedule.txt it is time to
remove the nfsctl system call.

Userspace has perferred to not use this call throughout 2.6 and it has been
excluded in the default configuration since 2.6.36 (9 months ago).

So this patch removes all the code that was being compiled out.

There are still references to sys_nfsctl in various arch systemcall tables
and related code.  These should be cleaned out too, probably in the next
merge window.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 094b5d74
......@@ -491,16 +491,6 @@ Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
----------------------------
What: access to nfsd auth cache through sys_nfsservctl or '.' files
in the 'nfsd' filesystem.
When: 2.6.40
Why: This is a legacy interface which have been replaced by a more
dynamic cache. Continuing to maintain this interface is an
unnecessary burden.
Who: NeilBrown <neilb@suse.de>
----------------------------
What: cancel_rearming_delayed_work[queue]()
When: 2.6.39
......
......@@ -1479,7 +1479,6 @@ CONFIG_NFS_FSCACHE=y
CONFIG_NFS_USE_KERNEL_DNS=y
# CONFIG_NFS_USE_NEW_IDMAPPER is not set
CONFIG_NFSD=m
CONFIG_NFSD_DEPRECATED=y
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
......
......@@ -29,7 +29,6 @@ obj-$(CONFIG_EVENTFD) += eventfd.o
obj-$(CONFIG_AIO) += aio.o
obj-$(CONFIG_FILE_LOCKING) += locks.o
obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
obj-$(CONFIG_NFSD_DEPRECATED) += nfsctl.o
obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
......
......@@ -1675,256 +1675,10 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
}
#endif /* HAVE_SET_RESTORE_SIGMASK */
#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
/* Stuff for NFS server syscalls... */
struct compat_nfsctl_svc {
u16 svc32_port;
s32 svc32_nthreads;
};
struct compat_nfsctl_client {
s8 cl32_ident[NFSCLNT_IDMAX+1];
s32 cl32_naddr;
struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
s32 cl32_fhkeytype;
s32 cl32_fhkeylen;
u8 cl32_fhkey[NFSCLNT_KEYMAX];
};
struct compat_nfsctl_export {
char ex32_client[NFSCLNT_IDMAX+1];
char ex32_path[NFS_MAXPATHLEN+1];
compat_dev_t ex32_dev;
compat_ino_t ex32_ino;
compat_int_t ex32_flags;
__compat_uid_t ex32_anon_uid;
__compat_gid_t ex32_anon_gid;
};
struct compat_nfsctl_fdparm {
struct sockaddr gd32_addr;
s8 gd32_path[NFS_MAXPATHLEN+1];
compat_int_t gd32_version;
};
struct compat_nfsctl_fsparm {
struct sockaddr gd32_addr;
s8 gd32_path[NFS_MAXPATHLEN+1];
compat_int_t gd32_maxlen;
};
struct compat_nfsctl_arg {
compat_int_t ca32_version; /* safeguard */
union {
struct compat_nfsctl_svc u32_svc;
struct compat_nfsctl_client u32_client;
struct compat_nfsctl_export u32_export;
struct compat_nfsctl_fdparm u32_getfd;
struct compat_nfsctl_fsparm u32_getfs;
} u;
#define ca32_svc u.u32_svc
#define ca32_client u.u32_client
#define ca32_export u.u32_export
#define ca32_getfd u.u32_getfd
#define ca32_getfs u.u32_getfs
};
union compat_nfsctl_res {
__u8 cr32_getfh[NFS_FHSIZE];
struct knfsd_fh cr32_getfs;
};
static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
struct compat_nfsctl_arg __user *arg)
{
if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
get_user(karg->ca_version, &arg->ca32_version) ||
__get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
__get_user(karg->ca_svc.svc_nthreads,
&arg->ca32_svc.svc32_nthreads))
return -EFAULT;
return 0;
}
static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
struct compat_nfsctl_arg __user *arg)
{
if (!access_ok(VERIFY_READ, &arg->ca32_client,
sizeof(arg->ca32_client)) ||
get_user(karg->ca_version, &arg->ca32_version) ||
__copy_from_user(&karg->ca_client.cl_ident[0],
&arg->ca32_client.cl32_ident[0],
NFSCLNT_IDMAX) ||
__get_user(karg->ca_client.cl_naddr,
&arg->ca32_client.cl32_naddr) ||
__copy_from_user(&karg->ca_client.cl_addrlist[0],
&arg->ca32_client.cl32_addrlist[0],
(sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
__get_user(karg->ca_client.cl_fhkeytype,
&arg->ca32_client.cl32_fhkeytype) ||
__get_user(karg->ca_client.cl_fhkeylen,
&arg->ca32_client.cl32_fhkeylen) ||
__copy_from_user(&karg->ca_client.cl_fhkey[0],
&arg->ca32_client.cl32_fhkey[0],
NFSCLNT_KEYMAX))
return -EFAULT;
return 0;
}
static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
struct compat_nfsctl_arg __user *arg)
{
if (!access_ok(VERIFY_READ, &arg->ca32_export,
sizeof(arg->ca32_export)) ||
get_user(karg->ca_version, &arg->ca32_version) ||
__copy_from_user(&karg->ca_export.ex_client[0],
&arg->ca32_export.ex32_client[0],
NFSCLNT_IDMAX) ||
__copy_from_user(&karg->ca_export.ex_path[0],
&arg->ca32_export.ex32_path[0],
NFS_MAXPATHLEN) ||
__get_user(karg->ca_export.ex_dev,
&arg->ca32_export.ex32_dev) ||
__get_user(karg->ca_export.ex_ino,
&arg->ca32_export.ex32_ino) ||
__get_user(karg->ca_export.ex_flags,
&arg->ca32_export.ex32_flags) ||
__get_user(karg->ca_export.ex_anon_uid,
&arg->ca32_export.ex32_anon_uid) ||
__get_user(karg->ca_export.ex_anon_gid,
&arg->ca32_export.ex32_anon_gid))
return -EFAULT;
SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
return 0;
}
static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
struct compat_nfsctl_arg __user *arg)
{
if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
sizeof(arg->ca32_getfd)) ||
get_user(karg->ca_version, &arg->ca32_version) ||
__copy_from_user(&karg->ca_getfd.gd_addr,
&arg->ca32_getfd.gd32_addr,
(sizeof(struct sockaddr))) ||
__copy_from_user(&karg->ca_getfd.gd_path,
&arg->ca32_getfd.gd32_path,
(NFS_MAXPATHLEN+1)) ||
__get_user(karg->ca_getfd.gd_version,
&arg->ca32_getfd.gd32_version))
return -EFAULT;
return 0;
}
static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
struct compat_nfsctl_arg __user *arg)
{
if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
get_user(karg->ca_version, &arg->ca32_version) ||
__copy_from_user(&karg->ca_getfs.gd_addr,
&arg->ca32_getfs.gd32_addr,
(sizeof(struct sockaddr))) ||
__copy_from_user(&karg->ca_getfs.gd_path,
&arg->ca32_getfs.gd32_path,
(NFS_MAXPATHLEN+1)) ||
__get_user(karg->ca_getfs.gd_maxlen,
&arg->ca32_getfs.gd32_maxlen))
return -EFAULT;
return 0;
}
/* This really doesn't need translations, we are only passing
* back a union which contains opaque nfs file handle data.
*/
static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
union compat_nfsctl_res __user *res)
{
int err;
err = copy_to_user(res, kres, sizeof(*res));
return (err) ? -EFAULT : 0;
}
asmlinkage long compat_sys_nfsservctl(int cmd,
struct compat_nfsctl_arg __user *arg,
union compat_nfsctl_res __user *res)
{
struct nfsctl_arg *karg;
union nfsctl_res *kres;
mm_segment_t oldfs;
int err;
karg = kmalloc(sizeof(*karg), GFP_USER);
kres = kmalloc(sizeof(*kres), GFP_USER);
if(!karg || !kres) {
err = -ENOMEM;
goto done;
}
switch(cmd) {
case NFSCTL_SVC:
err = compat_nfs_svc_trans(karg, arg);
break;
case NFSCTL_ADDCLIENT:
err = compat_nfs_clnt_trans(karg, arg);
break;
case NFSCTL_DELCLIENT:
err = compat_nfs_clnt_trans(karg, arg);
break;
case NFSCTL_EXPORT:
case NFSCTL_UNEXPORT:
err = compat_nfs_exp_trans(karg, arg);
break;
case NFSCTL_GETFD:
err = compat_nfs_getfd_trans(karg, arg);
break;
case NFSCTL_GETFS:
err = compat_nfs_getfs_trans(karg, arg);
break;
default:
err = -EINVAL;
break;
}
if (err)
goto done;
oldfs = get_fs();
set_fs(KERNEL_DS);
/* The __user pointer casts are valid because of the set_fs() */
err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres);
set_fs(oldfs);
if (err)
goto done;
if((cmd == NFSCTL_GETFD) ||
(cmd == NFSCTL_GETFS))
err = compat_nfs_getfh_res_trans(kres, res);
done:
kfree(karg);
kfree(kres);
return err;
}
#else /* !NFSD */
long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
{
return sys_ni_syscall();
}
#endif
#ifdef CONFIG_EPOLL
......
/*
* 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;
}
......@@ -28,18 +28,6 @@ config NFSD
If unsure, say N.
config NFSD_DEPRECATED
bool "Include support for deprecated syscall interface to NFSD"
depends on NFSD
default y
help
The syscall interface to nfsd was obsoleted in 2.6.0 by a new
filesystem based interface. The old interface is due for removal
in 2.6.40. If you wish to remove the interface before then
say N.
In unsure, say Y.
config NFSD_V2_ACL
bool
depends on NFSD
......
......@@ -797,58 +797,6 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
return ek;
}
#ifdef CONFIG_NFSD_DEPRECATED
static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
struct svc_export *exp)
{
struct svc_expkey key, *ek;
key.ek_client = clp;
key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
key.ek_path = exp->ex_path;
key.h.expiry_time = NEVER;
key.h.flags = 0;
ek = svc_expkey_lookup(&key);
if (ek)
ek = svc_expkey_update(&key,ek);
if (ek) {
cache_put(&ek->h, &svc_expkey_cache);
return 0;
}
return -ENOMEM;
}
/*
* Find the client's export entry matching xdev/xino.
*/
static inline struct svc_expkey *
exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
{
u32 fsidv[3];
if (old_valid_dev(dev)) {
mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
return exp_find_key(clp, FSID_DEV, fsidv, NULL);
}
mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
}
/*
* Find the client's export entry matching fsid
*/
static inline struct svc_expkey *
exp_get_fsid_key(svc_client *clp, int fsid)
{
u32 fsidv[2];
mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
return exp_find_key(clp, FSID_NUM, fsidv, NULL);
}
#endif
static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
struct cache_req *reqp)
......@@ -890,275 +838,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
return exp;
}
#ifdef CONFIG_NFSD_DEPRECATED
/*
* Hashtable locking. Write locks are placed only by user processes
* wanting to modify export information.
* Write locking only done in this file. Read locking
* needed externally.
*/
static DECLARE_RWSEM(hash_sem);
void
exp_readlock(void)
{
down_read(&hash_sem);
}
static inline void
exp_writelock(void)
{
down_write(&hash_sem);
}
void
exp_readunlock(void)
{
up_read(&hash_sem);
}
static inline void
exp_writeunlock(void)
{
up_write(&hash_sem);
}
#else
/* hash_sem not needed once deprecated interface is removed */
void exp_readlock(void) {}
static inline void exp_writelock(void){}
void exp_readunlock(void) {}
static inline void exp_writeunlock(void){}
#endif
#ifdef CONFIG_NFSD_DEPRECATED
static void exp_do_unexport(svc_export *unexp);
static int exp_verify_string(char *cp, int max);
static void exp_fsid_unhash(struct svc_export *exp)
{
struct svc_expkey *ek;
if ((exp->ex_flags & NFSEXP_FSID) == 0)
return;
ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
if (!IS_ERR(ek)) {
sunrpc_invalidate(&ek->h, &svc_expkey_cache);
cache_put(&ek->h, &svc_expkey_cache);
}
}
static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
{
u32 fsid[2];
if ((exp->ex_flags & NFSEXP_FSID) == 0)
return 0;
mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
return exp_set_key(clp, FSID_NUM, fsid, exp);
}
static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
{
u32 fsid[2];
struct inode *inode = exp->ex_path.dentry->d_inode;
dev_t dev = inode->i_sb->s_dev;
if (old_valid_dev(dev)) {
mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
return exp_set_key(clp, FSID_DEV, fsid, exp);
}
mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
}
static void exp_unhash(struct svc_export *exp)
{
struct svc_expkey *ek;
struct inode *inode = exp->ex_path.dentry->d_inode;
ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
if (!IS_ERR(ek)) {
sunrpc_invalidate(&ek->h, &svc_expkey_cache);
cache_put(&ek->h, &svc_expkey_cache);
}
}
/*
* Export a file system.
*/
int
exp_export(struct nfsctl_export *nxp)
{
svc_client *clp;
struct svc_export *exp = NULL;
struct svc_export new;
struct svc_expkey *fsid_key = NULL;
struct path path;
int err;
/* Consistency check */
err = -EINVAL;
if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
!exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
goto out;
dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
nxp->ex_client, nxp->ex_path,
(unsigned)nxp->ex_dev, (long)nxp->ex_ino,
nxp->ex_flags);
/* Try to lock the export table for update */
exp_writelock();
/* Look up client info */
if (!(clp = auth_domain_find(nxp->ex_client)))
goto out_unlock;
/* Look up the dentry */
err = kern_path(nxp->ex_path, 0, &path);
if (err)
goto out_put_clp;
err = -EINVAL;
exp = exp_get_by_name(clp, &path, NULL);
memset(&new, 0, sizeof(new));
/* must make sure there won't be an ex_fsid clash */
if ((nxp->ex_flags & NFSEXP_FSID) &&
(!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
fsid_key->ek_path.mnt &&
(fsid_key->ek_path.mnt