2005-04-17 02:20:36 +04:00
/*
* fs / nfsctl . c
*
* This should eventually move to userland .
*
*/
2006-01-19 04:44:07 +03:00
# include <linux/types.h>
2005-04-17 02:20:36 +04:00
# include <linux/file.h>
# include <linux/fs.h>
# include <linux/nfsd/syscall.h>
2008-11-19 22:46:46 +03:00
# include <linux/cred.h>
# include <linux/sched.h>
2005-04-17 02:20:36 +04:00
# 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 )
{
2007-07-19 12:48:21 +04:00
struct vfsmount * mnt ;
2011-03-11 20:08:24 +03:00
struct file * file ;
2005-04-17 02:20:36 +04:00
2007-07-19 12:48:21 +04:00
mnt = do_kern_mount ( " nfsd " , 0 , " nfsd " , NULL ) ;
if ( IS_ERR ( mnt ) )
return ( struct file * ) mnt ;
2005-04-17 02:20:36 +04:00
2011-03-11 20:08:24 +03:00
file = file_open_root ( mnt - > mnt_root , mnt , name , flags ) ;
2005-04-17 02:20:36 +04:00
2011-03-11 20:08:24 +03:00
mntput ( mnt ) ; /* drop do_kern_mount reference */
return file ;
2005-04-17 02:20:36 +04:00
}
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 )
} ,
} ;
2009-01-14 16:14:29 +03:00
SYSCALL_DEFINE3 ( nfsservctl , int , cmd , struct nfsctl_arg __user * , arg ,
void __user * , res )
2005-04-17 02:20:36 +04:00
{
struct file * file ;
void __user * p = & arg - > u ;
int version ;
int err ;
if ( copy_from_user ( & version , & arg - > ca_version , sizeof ( int ) ) )
return - EFAULT ;
2006-03-17 10:04:02 +03:00
if ( version ! = NFSCTL_VERSION )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
2006-03-24 14:15:34 +03:00
if ( cmd < 0 | | cmd > = ARRAY_SIZE ( map ) | | ! map [ cmd ] . name )
2005-04-17 02:20:36 +04:00
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 ;
}