NFS update

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4724 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-05-12 00:11:24 +00:00
parent 4bc440c90c
commit 95c738489d
6 changed files with 237 additions and 69 deletions

View File

@ -75,6 +75,7 @@ struct nfsmount
sem_t nm_sem; /* Used to assume thread-safe access */
int nm_numgrps; /* Max. size of groupslist */
nfsfh_t nm_fh; /* File handle of root dir */
char *nm_path; /* server's path of the directory being mount */
int nm_fhsize; /* Size of root file handle */
struct rpcclnt *nm_rpcclnt; /* rpc state */
struct socket *nm_so; /* Rpc socket */

View File

@ -144,7 +144,7 @@ int nfs_connect(struct nfsmount *nmp)
//rpc->rc_flag |= RPCCLNT_REDIRECT; /* Make this a mount option. */
rpc->rc_authtype = RPCAUTH_NULL; /* for now */
//rpc->rc_servername = nmp->nm_mountp->mnt_stat.f_mntfromname;
rpc->rc_path = nmp->nm_path;
rpc->rc_name = &nmp->nm_nam;
rpc->rc_sotype = nmp->nm_sotype;
@ -191,7 +191,9 @@ tryagain:
memset(&reply, 0, sizeof(reply));
if ((error = rpcclnt_request(clnt, procnum, &reply, datain)) != 0)
error = rpcclnt_request(clnt, procnum, nmp->nm_rpcclnt->rc_prog->prog_id,
nmp->nm_rpcclnt->rc_prog->prog_version, &reply, datain);
if (error != 0)
{
goto out;
}

View File

@ -995,7 +995,7 @@ int mountnfs(struct nfs_args *argp, void **handle)
{
struct nfsmount *nmp;
struct nfsnode *np;
int error;
int error = 0;
/* Create an instance of the mountpt state structure */
@ -1031,6 +1031,7 @@ int mountnfs(struct nfs_args *argp, void **handle)
//strncpy(&mp->mnt_stat.f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
//memmove(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
//bcopy(pth, nmp->nm_mntonname, 90);
nmp->nm_path = argp->path;
//memmove(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp));
nmp->nm_nam = argp->addr;
nfs_decode_args(nmp, argp);
@ -1064,6 +1065,7 @@ int mountnfs(struct nfs_args *argp, void **handle)
/* Mounted! */
nmp->nm_mounted = true;
nmp->nm_fh = nmp->nm_rpcclnt->rc_fh;
nmp->nm_so = nmp->nm_rpcclnt->rc_so;
*handle = (void*)nmp;
nfs_semgive(nmp);
@ -1130,7 +1132,8 @@ static int nfs_bind(struct inode *blkdriver, const void *data, void **handle)
int nfs_unbind(void *handle, struct inode **blkdriver)
{
struct nfsmount *nmp = (struct nfsmount *) handle ;
struct nfsmount *nmp = (struct nfsmount *)handle;
int error;
fvdbg("Entry\n");
@ -1140,6 +1143,14 @@ int nfs_unbind(void *handle, struct inode **blkdriver)
}
nfs_semtake(nmp);
error = rpcclnt_umount(nmp->nm_rpcclnt);
if (error)
{
dbg("Umounting fails %d\n", error);
goto bad;
}
nfs_disconnect(nmp);
sem_destroy(&nmp->nm_sem);
kfree(nmp->nm_head);
@ -1148,6 +1159,10 @@ int nfs_unbind(void *handle, struct inode **blkdriver)
kfree(nmp);
return 0;
bad:
nfs_disconnect(nmp);
return(error);
}
/****************************************************************************

View File

@ -10,7 +10,7 @@
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
@ -18,7 +18,7 @@
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
@ -84,7 +84,7 @@
#define RPCCLNT_SOFT 0x001 /* soft mount (hard is details) */
#define RPCCLNT_INT 0x002 /* allow interrupts on hard mounts */
#define RPCCLNT_NOCONN 0x004 /* dont connect the socket (udp) */
#define RPCCLNT_DUMBTIMR 0x010
#define RPCCLNT_DUMBTIMR 0x010
/* XXX should be replaced with real locks */
@ -93,10 +93,42 @@
#define RPCCLNT_RCVLOCK 0x400
#define RPCCLNT_WANTRCV 0x800
/* RPC definitions for the portmapper. */
#define PMAPPORT 111
#define PMAPPROG 100000
#define PMAPVERS 2
#define PMAPPROC_NULL 0
#define MAPPROC_SET 1
#define PMAPPROC_UNSET 2
#define PMAPPROC_GETPORT 3
#define PMAPPROC_DUMP 4
#define PMAPPROC_CALLIT 5
/****************************************************************************
* Public Types
****************************************************************************/
struct call_args_pmap
{
uint32_t prog;
uint32_t vers;
uint32_t proc;
uint32_t port;
};
struct call_result_pmap
{
uint16_t port;
unsigned char *extradata;
};
struct call_result_mount
{
uint16_t problem;
nfsfh_t fhandle;
};
struct rpc_program
{
uint32_t prog_id;
@ -107,9 +139,7 @@ struct rpc_program
struct rpctask
{
dq_entry_t r_chain;
struct rpcclnt *r_rpcclnt;
uint32_t r_xid;
int r_flags; /* flags on request, see below */
int r_retry; /* max retransmission count */
@ -146,7 +176,9 @@ struct rpc_call
uint32_t rp_proc; /* procedure */
unsigned char *data;
struct rpc_auth_info rpc_auth;
struct auth_unix rpc_unix;
#ifdef CONFIG_NFS_UNIX_AUTH
struct auth_unix rpc_unix;
#endif
struct rpc_auth_info rpc_verf;
};
@ -154,6 +186,7 @@ struct rpc_reply
{
uint32_t rp_xid; /* request transaction id */
int32_t rp_direction; /* call direction (1) */
struct
{
uint32_t type;
@ -173,7 +206,7 @@ struct rpc_reply
uint32_t high;
} mismatch_info;
} stat;
struct rpc_auth_info rpc_verfi;
};
@ -191,8 +224,10 @@ struct rpcclnt
int rc_wsize; /* Max size of the request data */
int rc_rsize; /* Max size of the response data */
nfsfh_t rc_fh; /* File handle of root dir */
char *rc_path; /* server's path of the directory being mount */
struct sockaddr *rc_name;
struct sockaddr *rc_name;
struct socket *rc_so; /* Rpc socket */
uint8_t rc_sotype; /* Type of socket */
@ -234,14 +269,12 @@ struct rpcclnt
****************************************************************************/
void rpcclnt_init(void);
//void rpcclnt_uninit(void);
//int rpcclnt_setup(struct rpcclnt *, struct rpc_program *, struct sockaddr *, int, int, struct rpc_auth_info *, int, int, int);
int rpcclnt_connect(struct rpcclnt *);
int rpcclnt_reconnect(struct rpctask *);
void rpcclnt_disconnect(struct rpcclnt *);
int rpcclnt_umount(struct rpcclnt *);
void rpcclnt_safedisconnect(struct rpcclnt *);
int rpcclnt_request(struct rpcclnt *, int, struct rpc_reply *, void *);
int rpcclnt_request(struct rpcclnt *, int, int, int, struct rpc_reply *, void *);
int rpcclnt_cancelreqs(struct rpcclnt *);

View File

@ -102,7 +102,7 @@
* Pre-processor Definitions
****************************************************************************/
#define RPC_RETURN(X) do { dbg("returning %d", X); return X; }while(0)
#define RPC_RETURN(X) do { nvdbg("returning %d\n", X); return X; } while(0)
/* Estimate rto for an nfs rpc sent via. an unreliable datagram. Use the mean
* and mean deviation of rtt for the appropriate type of rpc for the frequent
@ -223,7 +223,8 @@ static int rpcclnt_sigintr(struct rpcclnt *, struct rpctask *, cthread_t *);
static void rpcclnt_softterm(struct rpctask *task);
static uint32_t rpcclnt_proct(struct rpcclnt *, uint32_t);
static int rpcclnt_buildheader(struct rpcclnt *, int, void *, struct rpc_call *);
static int rpcclnt_buildheader(struct rpcclnt *, int, int, int, void *,
struct rpc_call *);
/****************************************************************************
* Private Functions
@ -294,7 +295,7 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, struct rpc_call *call,
}
error = psock_sendto(so, call, sizeof(*call), flags, sendnam, sizeof(*sendnam));
if (error != 0)
if (error < 0)
{
if (rep != NULL)
{
@ -317,16 +318,13 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, struct rpc_call *call,
ndbg("rpc service send error %d\n", error);
}
/* Handle any recoverable (soft) socket errors here. */
RPC_RETURN(error);
if (error != EINTR && error != ERESTART &&
error != EWOULDBLOCK && error != EPIPE)
{
error = 0;
}
}
RPC_RETURN(error);
else
{
RPC_RETURN(0);
}
}
/* Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all
@ -538,25 +536,20 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname,
RPC_RETURN(EACCES);
}
do
socklen_t fromlen = sizeof(*aname);
rcvflg = 0;
error = psock_recvfrom(so, reply, sizeof(*reply), rcvflg,
aname, &fromlen);
nvdbg("psock_recvfrom returns %d\n", error);
if (error > 0)
{
socklen_t fromlen = sizeof(*aname);
rcvflg = 0;
error = psock_recvfrom(so, reply, sizeof(*reply), rcvflg,
aname, &fromlen);
dbg("psock_recvfrom returns %d", error);
if (error == EWOULDBLOCK && (rep->r_flags & TASK_SOFTTERM))
{
dbg("wouldblock && softerm -> EINTR");
RPC_RETURN(EINTR);
}
RPC_RETURN(0);
}
while (error == EWOULDBLOCK);
#ifdef CONFIG_NFS_TCPIP
}
#endif
RPC_RETURN(error);
RPC_RETURN(ENONET);
}
/* Implement receipt of reply on a socket. We must search through the list of
@ -573,10 +566,11 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, //Here we need to m
int32_t t1;
uint32_t rxid;
int error;
int count;
/* Loop around until we get our own reply */
for (;;)
for (count = 0; count < 9; count++)
{
/* Lock against other receivers so that I don't get stuck in
* sbwait() after someone else has received my reply for me.
@ -594,7 +588,6 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, //Here we need to m
/* Get the next Rpc reply off the socket */
error = rpcclnt_receive(myrep, rpc->rc_name, reply, call);
#ifdef CONFIG_NFS_TCPIP
rpcclnt_rcvunlock(&rpc->rc_flag);
#endif
@ -612,7 +605,7 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, //Here we need to m
RPC_RETURN(0);
}
ndbg("ingoring routing error on connectionless protocol.");
ndbg("ignoring routing error on connectionless protocol.");
continue;
}
RPC_RETURN(error);
@ -698,8 +691,9 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, //Here we need to m
if (rep == 0)
{
ndbg("rpc reply not matched\n");
rpcstats.rpcunexpected++;
dbg("rpc reply not matched\n");
RPC_RETURN(ENOMSG);
}
else if (rep == myrep)
{
@ -711,6 +705,8 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, //Here we need to m
RPC_RETURN(0);
}
}
RPC_RETURN(ENONET);
}
#ifdef CONFIG_NFS_TCPIP
@ -923,7 +919,7 @@ void rpcclnt_init(void)
//rpcclnt_timer(NULL, callmgs);
nvdbg("rpc initialed");
nvdbg("rpc initialized");
return;
}
@ -946,6 +942,11 @@ int rpcclnt_connect(struct rpcclnt *rpc)
int error;
struct sockaddr *saddr;
struct sockaddr_in sin;
struct sockaddr_in *sa;
struct call_args_pmap sdata;
struct call_result_pmap *rdata;
struct call_result_mount *mdata;
struct rpc_reply reply;
struct timeval tv;
uint16_t tport;
@ -999,6 +1000,20 @@ int rpcclnt_connect(struct rpcclnt *rpc)
goto bad;
}
/* Always set receive timeout to detect server crash and reconnect.
* Otherwise, we can get stuck in psock_receive forever.
*/
tv.tv_sec = 1;
tv.tv_usec = 0;
error = psock_setsockopt(rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO,
(const void *)&tv, sizeof(tv));
if (error != 0)
{
goto bad;
}
/* Protocols that do not require connections may be optionally left
* unconnected for servers that reply from a port other than
* NFS_PORT.
@ -1011,31 +1026,74 @@ int rpcclnt_connect(struct rpcclnt *rpc)
goto bad;
}
else
{
#endif
{
error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
if (error)
{
dbg("psock_connect returns %d", error);
ndbg("psock_connect to ppmap port returns %d", error);
goto bad;
}
#ifdef CONFIG_NFS_TCPIP
}
#endif
/* Always set receive timeout to detect server crash and reconnect.
* Otherwise, we can get stuck in psock_receive forever.
*/
/* Do the RPC to get a dynamic bounding with the server using ppmap */
/* Get port number for MOUNTD. */
tv.tv_sec = 1;
tv.tv_usec = 0;
sdata.prog = txdr_unsigned(RPCPROG_MNT);
sdata.vers = txdr_unsigned(RPCMNT_VER1);
sdata.proc = txdr_unsigned(IPPROTO_UDP);
sdata.port = 0;
if ((error =
psock_setsockopt(rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO, (const void *)&tv,
sizeof(tv))))
{
goto bad;
memset(&reply, 0, sizeof(reply));
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
&reply, &sdata);
if (error != 0)
{
goto bad;
}
rdata = (struct call_result_pmap *)reply.stat.where;
sa = (FAR struct sockaddr_in *)saddr;
sa->sin_port = rdata->port;
error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
if (error)
{
ndbg("psock_connect NFS port returns %d\n", error);
goto bad;
}
/* Do RPC to mountd. */
memset(&reply, 0, sizeof(reply));
error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER1,
&reply, &rpc->rc_path);
if (error != 0)
{
goto bad;
}
mdata = (struct call_result_mount *)reply.stat.where;
rpc->rc_fh = mdata->fhandle;
if (mdata->problem)
{
ndbg("error mounting with the server %d\n", error);
goto bad;
}
/* NFS port in the socket*/
sa->sin_port = htons(NFS_PORT);
error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
if (error)
{
ndbg("psock_connect NFS port returns %d\n", error);
goto bad;
}
}
/* Initialize other non-zero congestion variables */
@ -1104,6 +1162,65 @@ void rpcclnt_disconnect(struct rpcclnt *rpc)
}
}
int rpcclnt_umount(struct rpcclnt *rpc)
{
struct sockaddr *saddr;
struct sockaddr_in *sa;
struct rpc_reply reply;
struct call_args_pmap sdata;
struct call_result_pmap *rdata;
int error;
saddr = rpc->rc_name;
/* Do the RPC to get a dynamic bounding with the server using ppmap*/
/* Get port number for MOUNTD. */
sdata.prog = txdr_unsigned(RPCPROG_MNT);
sdata.vers = txdr_unsigned(RPCMNT_VER1);
sdata.proc = txdr_unsigned(IPPROTO_UDP);
sdata.port = 0;
memset(&reply, 0, sizeof(reply));
error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS,
&reply, &sdata);
if (error != 0)
{
goto bad;
}
rdata = (struct call_result_pmap *)reply.stat.where;
sa = (FAR struct sockaddr_in *)saddr;
sa->sin_port = rdata->port;
error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr));
if (error)
{
ndbg("psock_connect umount port returns %d\n", error);
goto bad;
}
/* Do RPC to umountd. */
memset(&reply, 0, sizeof(reply));
error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER1,
&reply, &rpc->rc_path);
if (error != 0)
{
goto bad;
}
RPC_RETURN(0);
bad:
rpcclnt_disconnect(rpc);
RPC_RETURN(error);
}
#ifdef CONFIG_NFS_TCPIP
void rpcclnt_safedisconnect(struct rpcclnt *rpc)
{
@ -1127,13 +1244,13 @@ void rpcclnt_safedisconnect(struct rpcclnt *rpc)
* are invalid unless reply->type == RPC_MSGACCEPTED
*/
int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, void *datain)
int rpcclnt_request(struct rpcclnt *rpc, int procnum, int prog, int version,
struct rpc_reply *reply, void *datain)
{
struct rpc_call *callhost;
struct rpc_reply *replysvr;
struct rpctask *task;
int error = 0;
int xid = 0;
/* Create an instance of the call state structure */
@ -1162,7 +1279,7 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, v
return -ENOMEM;
}
error = rpcclnt_buildheader(rpc, procnum, datain, callhost);
error = rpcclnt_buildheader(rpc, procnum, prog, version, datain, callhost);
if (error)
{
ndbg("building call header error");
@ -1208,7 +1325,7 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, v
* now.
*/
if (rpc->rc_so && (rpc->rc_sotype != SOCK_DGRAM ||
if (rpc->rc_so && (rpc->rc_sotype == SOCK_DGRAM ||
(rpc->rc_flag & RPCCLNT_DUMBTIMR) ||
rpc->rc_sent < rpc->rc_cwnd))
{
@ -1218,7 +1335,6 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, v
error = rpcclnt_sndlock(&rpc->rc_flag, task);
}
#endif
if (error == 0)
{
error = rpcclnt_send(rpc->rc_so, rpc->rc_name, callhost, task);
@ -1248,6 +1364,7 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, v
{
error = rpcclnt_reply(task, callhost, replysvr);
}
nvdbg("out for reply %d\n", error);
/* RPC done, unlink the request. */
@ -1311,7 +1428,6 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, v
if (reply->stat.status == RPC_SUCCESS)
{
nvdbg("RPC_SUCCESS");
reply->stat.where = replysvr->stat.where;
}
else if (reply->stat.status == RPC_PROGMISMATCH)
@ -1475,7 +1591,7 @@ void rpcclnt_timer(void *arg, struct rpc_call *call)
/* Build the RPC header and fill in the authorization info. */
int rpcclnt_buildheader(struct rpcclnt *rpc, int procid,
int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int vers,
void *datain, struct rpc_call *call)
{
#ifdef CONFIG_NFS_UNIX_AUTH
@ -1507,8 +1623,8 @@ int rpcclnt_buildheader(struct rpcclnt *rpc, int procid,
call->rp_xid = txdr_unsigned(rpcclnt_xid);
call->rp_direction = rpc_call;
call->rp_rpcvers = rpc_vers;
call->rp_prog = txdr_unsigned(rpc->rc_prog->prog_id);
call->rp_vers = txdr_unsigned(rpc->rc_prog->prog_version);
call->rp_prog = txdr_unsigned(prog);
call->rp_vers = txdr_unsigned(vers);
call->rp_proc = txdr_unsigned(procid);
call->data = datain;

View File

@ -127,6 +127,7 @@ struct nfs_args
int readahead; /* # of blocks to readahead */
int leaseterm; /* Term (sec) of lease */
int deadthresh; /* Retrans threshold */
char *path; /* server's path of the directory being mount */
int acregmin; /* cache attrs for reg files min time */
int acregmax; /* cache attrs for reg files max time */
int acdirmin; /* cache attrs for dirs min time */