2005-04-17 02:20:36 +04:00
/*
* linux / fs / nfs / mount_clnt . c
*
* MOUNT client to support NFSroot .
*
* 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>
# ifdef RPC_DEBUG
# define NFSDBG_FACILITY NFSDBG_ROOT
# endif
/*
# define MOUNT_PROGRAM 100005
# define MOUNT_VERSION 1
# define MOUNT_MNT 1
# define MOUNT_UMNT 3
*/
static struct rpc_clnt * mnt_create ( char * , struct sockaddr_in * ,
int , int ) ;
static struct rpc_program mnt_program ;
struct mnt_fhstatus {
unsigned int status ;
struct nfs_fh * fh ;
} ;
/*
* Obtain an NFS file handle for the given host and path
*/
int
nfsroot_mount ( struct sockaddr_in * addr , char * path , struct nfs_fh * fh ,
int version , int protocol )
{
struct rpc_clnt * mnt_clnt ;
struct mnt_fhstatus result = {
. fh = fh
} ;
2006-03-20 21:44:23 +03:00
struct rpc_message msg = {
. rpc_argp = path ,
. rpc_resp = & result ,
} ;
2005-04-17 02:20:36 +04:00
char hostname [ 32 ] ;
int status ;
dprintk ( " NFS: nfs_mount(%08x:%s) \n " ,
( unsigned ) ntohl ( addr - > sin_addr . s_addr ) , path ) ;
sprintf ( hostname , " %u.%u.%u.%u " , NIPQUAD ( addr - > sin_addr . s_addr ) ) ;
mnt_clnt = mnt_create ( hostname , addr , version , protocol ) ;
if ( IS_ERR ( mnt_clnt ) )
return PTR_ERR ( mnt_clnt ) ;
2006-03-20 21:44:23 +03:00
if ( version = = NFS_MNT3_VERSION )
msg . rpc_proc = & mnt_clnt - > cl_procinfo [ MOUNTPROC3_MNT ] ;
else
msg . rpc_proc = & mnt_clnt - > cl_procinfo [ MNTPROC_MNT ] ;
status = rpc_call_sync ( mnt_clnt , & msg , 0 ) ;
2005-04-17 02:20:36 +04:00
return status < 0 ? status : ( result . status ? - EACCES : 0 ) ;
}
static struct rpc_clnt *
mnt_create ( char * hostname , struct sockaddr_in * srvaddr , int version ,
int protocol )
{
2006-08-28 01:23:53 +04:00
struct rpc_create_args args = {
. protocol = protocol ,
. address = ( struct sockaddr * ) srvaddr ,
. addrsize = sizeof ( * srvaddr ) ,
. servername = hostname ,
. program = & mnt_program ,
. version = version ,
. authflavor = RPC_AUTH_UNIX ,
. flags = ( RPC_CLNT_CREATE_ONESHOT |
RPC_CLNT_CREATE_INTR ) ,
} ;
return rpc_create ( & args ) ;
2005-04-17 02:20:36 +04:00
}
/*
* XDR encode / decode functions for MOUNT
*/
static int
2006-10-20 10:28:52 +04:00
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 ;
}
static int
2006-10-20 10:28:52 +04:00
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 ;
}
static int
2006-10-20 10:28:52 +04:00
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 ;
if ( ( res - > status = ntohl ( * p + + ) ) = = 0 ) {
int size = ntohl ( * p + + ) ;
if ( size < = NFS3_FHSIZE ) {
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
static struct rpc_procinfo mnt_procedures [ ] = {
[ MNTPROC_MNT ] = {
. p_proc = MNTPROC_MNT ,
. p_encode = ( kxdrproc_t ) xdr_encode_dirpath ,
. p_decode = ( kxdrproc_t ) xdr_decode_fhstatus ,
2007-03-30 00:47:53 +04:00
. p_arglen = MNT_dirpath_sz ,
. p_replen = MNT_fhstatus_sz ,
2006-03-20 21:44:22 +03:00
. p_statidx = MNTPROC_MNT ,
. p_name = " MOUNT " ,
2005-04-17 02:20:36 +04:00
} ,
} ;
static struct rpc_procinfo mnt3_procedures [ ] = {
[ MOUNTPROC3_MNT ] = {
. p_proc = MOUNTPROC3_MNT ,
. p_encode = ( kxdrproc_t ) xdr_encode_dirpath ,
. p_decode = ( kxdrproc_t ) xdr_decode_fhstatus3 ,
2007-03-30 00:47:53 +04:00
. p_arglen = MNT_dirpath_sz ,
. p_replen = MNT_fhstatus3_sz ,
2006-03-20 21:44:22 +03:00
. p_statidx = MOUNTPROC3_MNT ,
. p_name = " MOUNT " ,
2005-04-17 02:20:36 +04:00
} ,
} ;
static struct rpc_version mnt_version1 = {
. number = 1 ,
. nrprocs = 2 ,
. procs = mnt_procedures
} ;
static struct rpc_version mnt_version3 = {
. number = 3 ,
. nrprocs = 2 ,
. procs = mnt3_procedures
} ;
static struct rpc_version * mnt_version [ ] = {
NULL ,
& mnt_version1 ,
NULL ,
& mnt_version3 ,
} ;
static struct rpc_stat mnt_stats ;
static struct rpc_program mnt_program = {
. 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 ,
} ;