2005-04-17 02:20:36 +04:00
/*
2007-07-01 20:13:33 +04:00
* In - kernel MOUNT protocol client
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 1997 , Olaf Kirch < okir @ monad . swb . de >
*/
# include <linux/types.h>
# include <linux/socket.h>
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/uio.h>
# include <linux/net.h>
# include <linux/in.h>
# include <linux/sunrpc/clnt.h>
# include <linux/sunrpc/sched.h>
# include <linux/nfs_fs.h>
2008-04-12 04:03:06 +04:00
# include "internal.h"
2005-04-17 02:20:36 +04:00
# ifdef RPC_DEBUG
2007-07-01 20:13:27 +04:00
# define NFSDBG_FACILITY NFSDBG_MOUNT
2005-04-17 02:20:36 +04:00
# endif
2009-06-18 05:02:11 +04:00
/*
* Defined by RFC 1094 , section A .5
*/
enum {
MOUNTPROC_NULL = 0 ,
MOUNTPROC_MNT = 1 ,
MOUNTPROC_DUMP = 2 ,
MOUNTPROC_UMNT = 3 ,
MOUNTPROC_UMNTALL = 4 ,
MOUNTPROC_EXPORT = 5 ,
} ;
/*
* Defined by RFC 1813 , section 5.2
*/
enum {
MOUNTPROC3_NULL = 0 ,
MOUNTPROC3_MNT = 1 ,
MOUNTPROC3_DUMP = 2 ,
MOUNTPROC3_UMNT = 3 ,
MOUNTPROC3_UMNTALL = 4 ,
MOUNTPROC3_EXPORT = 5 ,
} ;
2005-04-17 02:20:36 +04:00
static struct rpc_program mnt_program ;
struct mnt_fhstatus {
2007-07-01 20:13:33 +04:00
u32 status ;
struct nfs_fh * fh ;
2005-04-17 02:20:36 +04:00
} ;
2007-07-01 20:13:27 +04:00
/**
* nfs_mount - Obtain an NFS file handle for the given host and path
2008-12-23 23:21:35 +03:00
* @ info : pointer to mount request arguments
2007-07-01 20:13:27 +04:00
*
* Uses default timeout parameters specified by underlying transport .
2005-04-17 02:20:36 +04:00
*/
2008-12-23 23:21:35 +03:00
int nfs_mount ( struct nfs_mount_request * info )
2005-04-17 02:20:36 +04:00
{
struct mnt_fhstatus result = {
2008-12-23 23:21:35 +03:00
. fh = info - > fh
2005-04-17 02:20:36 +04:00
} ;
2006-03-20 21:44:23 +03:00
struct rpc_message msg = {
2008-12-23 23:21:35 +03:00
. rpc_argp = info - > dirpath ,
2006-03-20 21:44:23 +03:00
. rpc_resp = & result ,
} ;
2007-07-01 20:13:27 +04:00
struct rpc_create_args args = {
2008-12-23 23:21:35 +03:00
. protocol = info - > protocol ,
. address = info - > sap ,
. addrsize = info - > salen ,
. servername = info - > hostname ,
2007-07-01 20:13:27 +04:00
. program = & mnt_program ,
2008-12-23 23:21:35 +03:00
. version = info - > version ,
2007-07-01 20:13:27 +04:00
. authflavor = RPC_AUTH_UNIX ,
} ;
struct rpc_clnt * mnt_clnt ;
2005-04-17 02:20:36 +04:00
int status ;
2007-07-01 20:13:27 +04:00
dprintk ( " NFS: sending MNT request for %s:%s \n " ,
2008-12-23 23:21:35 +03:00
( info - > hostname ? info - > hostname : " server " ) ,
info - > dirpath ) ;
2005-04-17 02:20:36 +04:00
2008-12-23 23:21:37 +03:00
if ( info - > noresvport )
args . flags | = RPC_CLNT_CREATE_NONPRIVPORT ;
2007-07-01 20:13:27 +04:00
mnt_clnt = rpc_create ( & args ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( mnt_clnt ) )
2007-07-01 20:13:38 +04:00
goto out_clnt_err ;
2005-04-17 02:20:36 +04:00
2008-12-23 23:21:35 +03:00
if ( info - > version = = NFS_MNT3_VERSION )
2006-03-20 21:44:23 +03:00
msg . rpc_proc = & mnt_clnt - > cl_procinfo [ MOUNTPROC3_MNT ] ;
else
2009-06-18 05:02:11 +04:00
msg . rpc_proc = & mnt_clnt - > cl_procinfo [ MOUNTPROC_MNT ] ;
2006-03-20 21:44:23 +03:00
status = rpc_call_sync ( mnt_clnt , & msg , 0 ) ;
2007-06-10 03:49:36 +04:00
rpc_shutdown_client ( mnt_clnt ) ;
2007-07-01 20:13:38 +04:00
if ( status < 0 )
goto out_call_err ;
if ( result . status ! = 0 )
goto out_mnt_err ;
dprintk ( " NFS: MNT request succeeded \n " ) ;
status = 0 ;
out :
return status ;
out_clnt_err :
status = PTR_ERR ( mnt_clnt ) ;
dprintk ( " NFS: failed to create RPC client, status=%d \n " , status ) ;
goto out ;
out_call_err :
dprintk ( " NFS: failed to start MNT request, status=%d \n " , status ) ;
goto out ;
out_mnt_err :
dprintk ( " NFS: MNT server returned result %d \n " , result . status ) ;
2008-04-12 04:03:06 +04:00
status = nfs_stat_to_errno ( result . status ) ;
2007-07-01 20:13:38 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
}
/*
* XDR encode / decode functions for MOUNT
*/
2007-07-01 20:13:33 +04:00
static int xdr_encode_dirpath ( struct rpc_rqst * req , __be32 * p ,
const char * path )
2005-04-17 02:20:36 +04:00
{
p = xdr_encode_string ( p , path ) ;
req - > rq_slen = xdr_adjust_iovec ( req - > rq_svec , p ) ;
return 0 ;
}
2007-07-01 20:13:33 +04:00
static int xdr_decode_fhstatus ( struct rpc_rqst * req , __be32 * p ,
struct mnt_fhstatus * res )
2005-04-17 02:20:36 +04:00
{
struct nfs_fh * fh = res - > fh ;
if ( ( res - > status = ntohl ( * p + + ) ) = = 0 ) {
fh - > size = NFS2_FHSIZE ;
memcpy ( fh - > data , p , NFS2_FHSIZE ) ;
}
return 0 ;
}
2007-07-01 20:13:33 +04:00
static int xdr_decode_fhstatus3 ( struct rpc_rqst * req , __be32 * p ,
struct mnt_fhstatus * res )
2005-04-17 02:20:36 +04:00
{
struct nfs_fh * fh = res - > fh ;
2008-06-19 23:21:11 +04:00
unsigned size ;
2005-04-17 02:20:36 +04:00
if ( ( res - > status = ntohl ( * p + + ) ) = = 0 ) {
2008-06-19 23:21:11 +04:00
size = ntohl ( * p + + ) ;
if ( size < = NFS3_FHSIZE & & size ! = 0 ) {
2005-04-17 02:20:36 +04:00
fh - > size = size ;
memcpy ( fh - > data , p , size ) ;
} else
res - > status = - EBADHANDLE ;
}
return 0 ;
}
# define MNT_dirpath_sz (1 + 256)
# define MNT_fhstatus_sz (1 + 8)
2007-03-30 00:47:53 +04:00
# define MNT_fhstatus3_sz (1 + 16)
2005-04-17 02:20:36 +04:00
2007-07-01 20:13:33 +04:00
static struct rpc_procinfo mnt_procedures [ ] = {
2009-06-18 05:02:11 +04:00
[ MOUNTPROC_MNT ] = {
. p_proc = MOUNTPROC_MNT ,
2007-07-01 20:13:33 +04:00
. p_encode = ( kxdrproc_t ) xdr_encode_dirpath ,
. p_decode = ( kxdrproc_t ) xdr_decode_fhstatus ,
. p_arglen = MNT_dirpath_sz ,
. p_replen = MNT_fhstatus_sz ,
2009-06-18 05:02:11 +04:00
. p_statidx = MOUNTPROC_MNT ,
2007-07-01 20:13:33 +04:00
. p_name = " MOUNT " ,
2005-04-17 02:20:36 +04:00
} ,
} ;
static struct rpc_procinfo mnt3_procedures [ ] = {
2007-07-01 20:13:33 +04:00
[ MOUNTPROC3_MNT ] = {
. p_proc = MOUNTPROC3_MNT ,
. p_encode = ( kxdrproc_t ) xdr_encode_dirpath ,
. p_decode = ( kxdrproc_t ) xdr_decode_fhstatus3 ,
. p_arglen = MNT_dirpath_sz ,
. p_replen = MNT_fhstatus3_sz ,
. p_statidx = MOUNTPROC3_MNT ,
. p_name = " MOUNT " ,
2005-04-17 02:20:36 +04:00
} ,
} ;
2007-07-01 20:13:33 +04:00
static struct rpc_version mnt_version1 = {
. number = 1 ,
. nrprocs = 2 ,
. procs = mnt_procedures ,
2005-04-17 02:20:36 +04:00
} ;
2007-07-01 20:13:33 +04:00
static struct rpc_version mnt_version3 = {
. number = 3 ,
. nrprocs = 2 ,
. procs = mnt3_procedures ,
2005-04-17 02:20:36 +04:00
} ;
2007-07-01 20:13:33 +04:00
static struct rpc_version * mnt_version [ ] = {
2005-04-17 02:20:36 +04:00
NULL ,
& mnt_version1 ,
NULL ,
& mnt_version3 ,
} ;
2007-07-01 20:13:33 +04:00
static struct rpc_stat mnt_stats ;
2005-04-17 02:20:36 +04:00
2007-07-01 20:13:33 +04:00
static struct rpc_program mnt_program = {
2005-04-17 02:20:36 +04:00
. name = " mount " ,
. number = NFS_MNT_PROGRAM ,
2006-03-24 14:15:34 +03:00
. nrvers = ARRAY_SIZE ( mnt_version ) ,
2005-04-17 02:20:36 +04:00
. version = mnt_version ,
. stats = & mnt_stats ,
} ;