summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/fs/nfs/nfs_mount.h1
-rw-r--r--nuttx/fs/nfs/nfs_socket.c6
-rw-r--r--nuttx/fs/nfs/nfs_vfsops.c19
-rw-r--r--nuttx/fs/nfs/rpc.h57
-rw-r--r--nuttx/fs/nfs/rpc_clnt.c222
-rw-r--r--nuttx/include/nuttx/fs/nfs.h1
6 files changed, 237 insertions, 69 deletions
diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h
index 26b3eb2f9..cd3980f79 100644
--- a/nuttx/fs/nfs/nfs_mount.h
+++ b/nuttx/fs/nfs/nfs_mount.h
@@ -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 */
diff --git a/nuttx/fs/nfs/nfs_socket.c b/nuttx/fs/nfs/nfs_socket.c
index fc658a481..c1508171d 100644
--- a/nuttx/fs/nfs/nfs_socket.c
+++ b/nuttx/fs/nfs/nfs_socket.c
@@ -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;
}
diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c
index bfdc2e955..879c21ed2 100644
--- a/nuttx/fs/nfs/nfs_vfsops.c
+++ b/nuttx/fs/nfs/nfs_vfsops.c
@@ -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);
}
/****************************************************************************
diff --git a/nuttx/fs/nfs/rpc.h b/nuttx/fs/nfs/rpc.h
index fe93a6e4d..f6b8d6674 100644
--- a/nuttx/fs/nfs/rpc.h
+++ b/nuttx/fs/nfs/rpc.h
@@ -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 *);
diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c
index 0e72ff5b0..ab0a381b9 100644
--- a/nuttx/fs/nfs/rpc_clnt.c
+++ b/nuttx/fs/nfs/rpc_clnt.c
@@ -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;
diff --git a/nuttx/include/nuttx/fs/nfs.h b/nuttx/include/nuttx/fs/nfs.h
index 423c212e6..431c1d130 100644
--- a/nuttx/include/nuttx/fs/nfs.h
+++ b/nuttx/include/nuttx/fs/nfs.h
@@ -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 */