diff options
author | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2012-04-14 00:27:44 +0000 |
---|---|---|
committer | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2012-04-14 00:27:44 +0000 |
commit | df5c47bfaeeba223f006e9f35df0edbc68057760 (patch) | |
tree | 403582e0c293d0bef2e51306de8d6a2982a7f279 | |
parent | 81339344802a755fdc3738bada9f5df2bd6fa3da (diff) | |
download | px4-firmware-df5c47bfaeeba223f006e9f35df0edbc68057760.tar.gz px4-firmware-df5c47bfaeeba223f006e9f35df0edbc68057760.tar.bz2 px4-firmware-df5c47bfaeeba223f006e9f35df0edbc68057760.zip |
NFS client update
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4605 7fd9a85b-ad96-42d3-883c-3090e2eb8679
-rw-r--r-- | nuttx/fs/nfs/nfs.h | 148 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_mount.h | 2 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_node.h | 1 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_socket.c | 57 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_socket.h | 8 | ||||
-rw-r--r-- | nuttx/fs/nfs/nfs_vfsops.c | 623 | ||||
-rw-r--r-- | nuttx/fs/nfs/rpc.h | 3 | ||||
-rw-r--r-- | nuttx/fs/nfs/rpc_clnt.c | 386 |
8 files changed, 710 insertions, 518 deletions
diff --git a/nuttx/fs/nfs/nfs.h b/nuttx/fs/nfs/nfs.h index 88276123c..d9e61e57c 100644 --- a/nuttx/fs/nfs/nfs.h +++ b/nuttx/fs/nfs/nfs.h @@ -73,9 +73,9 @@ /* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with * broken NFS/ethernet drivers that won't work with anything bigger (Linux..) */ - -#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */ -#define NFS_READDIRBLKSIZ 512 /* Size of read dir blocks. XXX */ + +#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */ +#define NFS_READDIRBLKSIZ 512 /* Size of read dir blocks. XXX */ /* Oddballs */ @@ -102,17 +102,17 @@ * buffer cache code to say "Invalidate the block after it is written back". */ -#define B_INVAFTERWRITE B_INVAL +#define B_INVAFTERWRITE B_INVAL /* Flags for nfssvc() system call. */ -#define NFSSVC_BIOD 0x002 -#define NFSSVC_NFSD 0x004 -#define NFSSVC_ADDSOCK 0x008 -#define NFSSVC_AUTHIN 0x010 -#define NFSSVC_GOTAUTH 0x040 +#define NFSSVC_BIOD 0x002 +#define NFSSVC_NFSD 0x004 +#define NFSSVC_ADDSOCK 0x008 +#define NFSSVC_AUTHIN 0x010 +#define NFSSVC_GOTAUTH 0x040 #define NFSSVC_AUTHINFAIL 0x080 -#define NFSSVC_MNTD 0x100 +#define NFSSVC_MNTD 0x100 /* fs.nfs sysctl(3) identifiers */ @@ -129,8 +129,7 @@ #define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \ sigmask(SIGHUP)|sigmask(SIGQUIT)) -/* - * Socket errors ignored for connectionless sockets?? +/* Socket errors ignored for connectionless sockets?? * For now, ignore them all */ @@ -316,7 +315,7 @@ struct nfssvc_sock int ns_solock; /* lock for connected socket */ int ns_cc; /* actual chars queued */ int ns_reclen; /* length of first queued record */ - uint32_t ns_sref; /* # of refs to this struct */ + uint32_t ns_sref; /* # of refs to this struct */ }; /* One of these structures is allocated for each nfsd. */ @@ -324,19 +323,127 @@ struct nfssvc_sock struct nfsd { //TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */ - int nfsd_flag; /* NFSD_ flags */ - struct nfssvc_sock *nfsd_slp; /* Current socket */ - struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */ + int nfsd_flag; /* NFSD_ flags */ + struct nfssvc_sock *nfsd_slp; /* Current socket */ + struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */ }; /* This structure is used by the server for describing each request. */ struct nfsrv_descript { - unsigned int nd_procnum; /* RPC # */ - int nd_flag; /* nd_flag */ - int nd_repstat; /* Reply status */ - uint32_t nd_retxid; /* Reply xid */ + unsigned int nd_procnum; /* RPC # */ + int nd_flag; /* nd_flag */ + int nd_repstat; /* Reply status */ + uint32_t nd_retxid; /* Reply xid */ +}; + +/* NFS procedures args */ + +struct wcc_attr +{ + nfsuint64 size; + nfstime3 mtime; + nfstime3 ctime; +} + +struct wcc_data +{ + wcc_attr before; + nfs_fattr after; +}; + +struct diropargs3 +{ + nfsfh_t dir; + const char name; +}; + +struct CREATE3args +{ + diropargs3 where; + nfsv3_sattr how; +}; + +struct CREATE3resok +{ + const char handle; + nfs_fattr attributes; + wcc_data dir_wcc; +}; + +struct READ3args +{ + nfstype file; + uint64_t offset; + uint32_t count; +}; + +struct READ3resok +{ + nfs_fattr file_attributes; + uint32_t count; + bool eof; + const char data; +}; + +enum stable_how +{ + UNSTABLE = 0, + DATA_SYNC = 1, + FILE_SYNC = 2 +}; + +struct WRITE3args +{ + nfstype file; + uint64_t offset; + uint32_t count; + stable_how stable; + const char data; +}; + +struct WRITE3resok +{ + wcc_data file_wcc; + count3 count; + stable_how committed; + unsigned char verf; +}; + +struct REMOVE3args +{ + diropargs3 object; +}; + +struct REMOVE3resok +{ + wcc_data dir_wcc; +}; + +struct RENAME3args +{ + diropargs3 from; + diropargs3 to; +}; + +struct RENAME3resok +{ + wcc_data fromdir_wcc; + wcc_data todir_wcc; +}; + +struct MKDIR3args +{ + diropargs3 where; + nfsv3_sattr attributes; +}; + +struct MKDIR3resok +{ + const char handle; + nfs_fattr obj_attributes; + wcc_data dir_wcc; }; /**************************************************************************** @@ -352,6 +459,7 @@ extern struct pool nfs_node_pool; extern TAILQ_HEAD(nfsdhead, nfsd) nfsd_head; extern int nfsd_head_flag; */ + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h index 1cc96963d..5c0e5a5fd 100644 --- a/nuttx/fs/nfs/nfs_mount.h +++ b/nuttx/fs/nfs/nfs_mount.h @@ -98,7 +98,7 @@ struct nfsmount int nm_acregmin; /* Reg file attr cache min lifetime */ int nm_acregmax; /* Reg file attr cache max lifetime */ unsigned char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */ - char nm_mntonname[90]; /* directory on which mounted */ +//char nm_mntonname[90]; /* directory on which mounted */ uint8_t *nm_buffer; /* This is an allocated buffer to hold one sector*/ }; diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h index 5a0476572..dd7fe12a8 100644 --- a/nuttx/fs/nfs/nfs_node.h +++ b/nuttx/fs/nfs/nfs_node.h @@ -115,7 +115,6 @@ struct nfsnode bool n_open; /* true: The file is (still) open */ uint64_t n_size; /* Current size of file */ struct nfs_fattr n_fattr; /* nfs file attribute cache */ - struct nfsv3_sattr n_sattr; nfstype nfsv3_type; /* File type */ time_t n_attrstamp; /* Attr. cache timestamp */ struct timespec n_mtime; /* Prev modify time. */ diff --git a/nuttx/fs/nfs/nfs_socket.c b/nuttx/fs/nfs/nfs_socket.c index c1953369c..663cf8e26 100644 --- a/nuttx/fs/nfs/nfs_socket.c +++ b/nuttx/fs/nfs/nfs_socket.c @@ -61,11 +61,13 @@ /* Flag translations */ -#define nfsmnt_to_rpcclnt(nf, rf, name) do { \ - if (nf & NFSMNT_##name) { \ - rf |= RPCCLNT_##name; \ - } \ -} while(0) +#define nfsmnt_to_rpcclnt(nf, rf, name) do \ + { \ + if (nf & NFSMNT_##name) \ + { \ + rf |= RPCCLNT_##name; \ + } \ + } while(0) /**************************************************************************** * Private Variables @@ -101,15 +103,18 @@ int nfsx_connect(struct nfsmount *nmp) int error = 0; if (nmp == NULL) - return EFAULT; + { + return EFAULT; + } rpc = &nmp->nm_rpcclnt; rpc->rc_prog = &nfs3_program; - printf("nfsxconnect!\n"); + nvdbg("nfsxconnect!\n"); /* translate nfsmnt flags -> rpcclnt flags */ + rpc->rc_flag = 0; nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, SOFT); nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, INT); @@ -132,11 +137,14 @@ int nfsx_connect(struct nfsmount *nmp) rpc->rc_retry = nmp->nm_retry; /* XXX v2,3 need to use this */ + rpc->rc_proctlen = 0; rpc->rc_proct = NULL; if (error) - return error; + { + return error; + } return rpcclnt_connect(rpc); } @@ -155,7 +163,7 @@ void nfsx_safedisconnect(struct nfsmount *nmp) } #endif -int nfsx_request_xx(struct nfsmount *nm, int procnum, void *data) +int nfsx_request_xx(struct nfsmount *nm, int procnum,void *datain, void *dataout) { int error; struct nfsmount *nmp; @@ -170,10 +178,12 @@ tryagain: memset(reply, 0, sizeof(struct rpc_reply)); - if ((error = rpcclnt_request(clnt, procnum, reply)) != 0) - goto out; + if ((error = rpcclnt_request(clnt, procnum, reply, datain)) != 0) + { + goto out; + } - data = reply->stat.where; + dataout = reply->stat.where; if (reply->rpc_verfi.authtype != 0) { @@ -190,22 +200,27 @@ tryagain: goto tryagain; } - /* - ** If the File Handle was stale, invalidate the - ** lookup cache, just in case. - **/ + /* If the File Handle was stale, invalidate the + * lookup cache, just in case. + */ + if (error == ESTALE) - printf("%s: ESTALE on mount from server \n", - nmp->nm_rpcclnt.rc_prog->prog_name); + { + ndbg("%s: ESTALE on mount from server \n", + nmp->nm_rpcclnt.rc_prog->prog_name); + } else - printf("%s: unknown error %d from server \n", + { + ndbg("%s: unknown error %d from server \n", nmp->nm_rpcclnt.rc_prog->prog_name, error); + } + goto out; } - return (0); + return 0; out: - return (error); + return error; } /* terminate any outstanding RPCs. */ diff --git a/nuttx/fs/nfs/nfs_socket.h b/nuttx/fs/nfs/nfs_socket.h index f1be14aa2..e668e85fb 100644 --- a/nuttx/fs/nfs/nfs_socket.h +++ b/nuttx/fs/nfs/nfs_socket.h @@ -53,17 +53,17 @@ int nfsx_sigintr(struct nfsmount *, struct nfsreq *, cthread_t *); void nfsx_safedisconnect(struct nfsmount *); #define nfs_safedisconnect nfsx_safedisconnect #endif -int nfsx_request_xx(struct nfsmount *, int, void*); +int nfsx_request_xx(struct nfsmount *, int, void*, void*); int nfsx_nmcancelreqs(struct nfsmount *); #define nfs_connect nfs_connect_nfsx #define nfs_disconnect nfs_disconnect_nfsx #define nfs_nmcancelreqs nfsx_nmcancelreqs -#define nfsx_request(nmp, m, s) \ - nfsx_request_xx(nmp, m, s) +#define nfsx_request(nmp, m, i, o) \ + nfsx_request_xx(nmp, m, i, o) #ifdef CONFIG_NFS_TCPIP -#define nfs_sigintr nfs_sigintr_nfsx +# define nfs_sigintr nfs_sigintr_nfsx #endif #endif /* __FS_NFS_NFS_SOCKET_H */ diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c index 345b80bb7..4d14feac9 100644 --- a/nuttx/fs/nfs/nfs_vfsops.c +++ b/nuttx/fs/nfs/nfs_vfsops.c @@ -48,9 +48,12 @@ #include <sys/socketvar.h> #include <sys/systm.h> #include <sys/sysctl.h> - #include <sys/statfs> + #include <queue.h> +#include <assert.h> +#include <errno.h> +#include <debug.h> #include <nuttx/fs/dirent.h> #include <nuttx/fs/fs.h> @@ -140,21 +143,17 @@ const struct mountpt_operations nfs_ops = { */ int -nfs_open(FAR struct file *filp, FAR const char *relpath, +nfs_open(FAR struct file *filp, FAR const char *relpath, // done but check variable how int oflags, mode_t mode) { - // struct vop_create_args *ap = v; struct inode *in; - struct nfsv3_sattr *vap; - // struct componentname *cnp = ap->a_cnp; + struct nfs_fattr *vap; struct nfsv3_sattr *sp; struct nfsmount *nmp; - // struct nfsm_info info; - //uint32_t *tl; - //int32_t t1; struct nfsnode *np; + struct CREATE3args *create; + struct CREATE3resok *resok; void *replydata; - int info_v3; int error = 0; /* Sanity checks */ @@ -167,8 +166,7 @@ nfs_open(FAR struct file *filp, FAR const char *relpath, in = filep->f_inode; nmp = (struct nfsmount*)in->i_private; - info_v3 = (nmp->nm_flag & NFSMNT_NFSV3); - vap = nmp->nm_head->n_sattr; + np = (struct nfsnode*)filep->f_priv; DEBUGASSERT(nmp != NULL); @@ -183,24 +181,28 @@ nfs_open(FAR struct file *filp, FAR const char *relpath, if (oflags == O_CREAT) { - /* Sanity checks */ + /* Sanity checks */ DEBUGASSERT(filep->f_priv == NULL); - again: +again: nfsstats.rpccnt[NFSPROC_CREATE]++; - + vap = nmp->nm_head->n_fattr; sp->sa_modetrue = nfs_true; - sp->sa_mode = txdr_unsigned(vap->sa_mode); + sp->sa_mode = txdr_unsigned(vap->fa_mode); sp->sa_uid = nfs_xdrneg1; sp->sa_gid = nfs_xdrneg1; sp->sa_size = nfs_xdrneg1; sp->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); sp->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); - txdr_nfsv3time(&vap->sa_atime, &sp->sa_atime); - txdr_nfsv3time(&vap->sa_mtime, &sp->sa_mtime); + txdr_nfsv3time(&vap->fa_atime, &sp->sa_atime); + txdr_nfsv3time(&vap->fa_mtime, &sp->sa_mtime); - error = nfs_request(in, NFSPROC_CREATE, replydata); + create->how = sp; + create->where->dir= nmp->nm_fh; + create->where->name = relpath; + + error = nfs_request(in, NFSPROC_CREATE, (void *) create, replydata); if (!error) { /* Create an instance of the file private data to describe the opened @@ -219,9 +221,13 @@ nfs_open(FAR struct file *filp, FAR const char *relpath, * non-zero elements) */ + resok = (struct CREATE3resok *) replydata; np->n_open = true; - np->n_size = sp->sa_size; - np->n_sattr = sp; + np->nfsv3_type = NFREG; + np->n_size = (struct uint64_t *)resok->attributes->nfsv3fa_size; + np->n_fattr = resok->attributes; + np->n_mtime = (struct timespec*) resok->attributes->nfsv3fa_mtime + np->n_ctime = (struct time_t*) resok->attributes->nfsv3fa_ctime /* Attach the private date to the struct file instance */ @@ -244,6 +250,7 @@ nfs_open(FAR struct file *filp, FAR const char *relpath, goto again; } } + np->n_flag |= NMODIFIED; } else @@ -254,10 +261,12 @@ nfs_open(FAR struct file *filp, FAR const char *relpath, return EACCES; } - NFS_INVALIDATE_ATTRCACHE(np); - if (np->nfsv3_type == NFDIR) + if (np->n_flag & NMODIFIED) { - np->n_direofoffset = 0; + if (np->nfsv3_type == NFDIR) + { + np->n_direofoffset = 0; + } } } @@ -307,21 +316,21 @@ int nfs_close(FAR struct file *filep) //done * Name: nfs_read ****************************************************************************/ -int nfs_read(FAR struct file *filep, char *buffer, size_t buflen) +static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) //done { struct nfsmount *nmp; struct nfsnode *np; - unsigned int bytesread; unsigned int readsize; - int biosize, diff; + int bytesleft; + uint64_t offset; void *datareply; - void baddr; + struct READ3args *read; + struct READ3resok *resok; + uint8_t *userbuffer = (uint8_t*)buffer; int info_v3; int error = 0; int len; - int retlen; - int tsiz; - int eof; + bool eof; fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); @@ -331,11 +340,10 @@ int nfs_read(FAR struct file *filep, char *buffer, size_t buflen) /* Recover our private data from the struct file instance */ - np = filep->f_priv; - nmp = filep->f_inode->i_private; - info_v3 = (nmp->nm_flag & NFSMNT_NFSV3); - eof = 0; - tsiz = (int) buflen; + np = (struct nfsnode*) filep->f_priv; + nmp = (struct nfsmount*) filep->f_inode->i_private; + eof = false; + offset = 0; DEBUGASSERT(nmp != NULL); @@ -360,9 +368,10 @@ int nfs_read(FAR struct file *filep, char *buffer, size_t buflen) (void)nfs_fsinfo(nmp); } - /* Get the number of bytes left in the file */ + /* Get the number of bytes left in the file */ bytesleft = np->n_size - filep->f_pos; + readsize = 0; /* Truncate read count so that it does not exceed the number * of bytes left in the file. @@ -373,78 +382,83 @@ int nfs_read(FAR struct file *filep, char *buffer, size_t buflen) buflen = bytesleft; } - readsize = 0; - while (tsiz > 0) - { + len = nmp->nm_rsize; + if (len < buflen) + { + error = EFBIG + goto errout_with_semaphore; + + } + nfsstats.rpccnt[NFSPROC_READ]++; - len = nmp->nm_rsize; +again: + read->file = np->nfsv3_type; + read->count = buflen; + read->offset = offset; - error = nfs_request(vp, NFSPROC_READ, datareply); + error = nfs_request(nmp, NFSPROC_READ, read, datareply); if (error) { goto errout_with_semaphore; } - if (info_v3) + resok = (struct READ3resok *) datareply; + eof = resok->eof; + if (eof == true) { - eof = fxdr_unsigned(int, datareply); - } + readsize = resok->count; + np->n_fattr = resok->file_attributes; + memcpy(userbuffer, resok->data, (struct size_t)readsize); - retlen = fxdr_unsigned(int, nmp->nm_rsize); - tsiz -= retlen; - if (info_v3) - { - if (eof || retlen == 0) - { - tsiz = 0; - } } - else if (retlen < len) + else { - tsiz = 0; + goto again; } - } - nfs_semgive(nmp); +nfs_semgive(nmp); return readsize; errout_with_semaphore: nfs_semgive(nmp); - return (error); + return error; } +/**************************************************************************** + * Name: nfs_write + ****************************************************************************/ -/* nfs write call */ - -int -nfs_writerpc(FAR struct file *filep, const char *buffer, size_t buflen) +static ssize_t +nfs_write(FAR struct file *filep, const char *buffer, size_t buflen) // done { - struct nfsm_info info; + /*struct nfsm_info info; uint32_t *tl; int32_t t1, backup; - caddr_t cp2; + caddr_t cp2;*/ + struct inode *inode; struct nfsmount *nmp; struct nfsnode *np; + unsigned int writesize; void *datareply; + struct WRITE3args *write; + struct WRITE3resok resok; + uint8_t *userbuffer = (uint8_t*)buffer; int error = 0; + uint64_t offset; int len; - int tsiz; - int wccflag = NFSV3_WCCRATTR; - int rlen; - int commit; + struct stable_how commit; int committed = NFSV3WRITE_FILESYNC; - info.nmi_v3 = NFS_ISV3(vp); - - /* Sanity checks */ + /* Sanity checks */ DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); /* Recover our private data from the struct file instance */ - np = filep->f_priv; - inode = filep->f_inode; - nmp = inode->i_private; + np = (struct nfsnode *)filep->f_priv; + inode = filep->f_inode; + nmp = (struct nfsmount *)inode->i_private; + offset = 0; DEBUGASSERT(nmp != NULL); @@ -465,84 +479,68 @@ nfs_writerpc(FAR struct file *filep, const char *buffer, size_t buflen) goto errout_with_semaphore; } - //*must_commit = 0; - tsiz = (int) buflen; - - while (tsiz > 0) + len = nmp->nm_wsize; + if (len < buflen) { - nfsstats.rpccnt[NFSPROC_WRITE]++; - len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; - - error = nfs_request(vp, NFSPROC_WRITE, datareply); + error = -EFBIG + goto errout_with_semaphore; + } + writesize = 0; - if (error) - { - goto errout_with_semaphore; - } + nfsstats.rpccnt[NFSPROC_WRITE]++; + write->file = np->nfsv3_type; + write->offset = offset; + write->count = buflen; + write->stable = committed; + memcpy(write->data, userbuffer, buflen); - if (info.nmi_v3) - { - wccflag = NFSV3_WCCCHK; - nfsm_dissect(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_V3WRITEVERF); - rlen = fxdr_unsigned(int, *tl++); - if (rlen == 0) - { - error = NFSERR_IO; - goto errout_with_semaphore; - } - else if (rlen < len) - { - backup = len - rlen; - uiop->uio_iov->iov_base = - (char *)uiop->uio_iov->iov_base - backup; - uiop->uio_iov->iov_len += backup; - uiop->uio_offset -= backup; - uiop->uio_resid += backup; - len = rlen; - } - commit = fxdr_unsigned(int, *tl++); + error = nfs_request(nmp, NFSPROC_WRITE, write, datareply); + if (error) + { + goto errout_with_semaphore; + } - /* Return the lowest committment level - * obtained by any of the RPCs. - */ + resok = (struct WRITE3resok *)datareply; + writesize = resok->count; + if (writesize == 0) + { + error = -NFSERR_IO; + goto errout_with_semaphore; + } - if (committed == NFSV3WRITE_FILESYNC) - { - committed = commit; - } - else if (committed == NFSV3WRITE_DATASYNC && - commit == NFSV3WRITE_UNSTABLE) - { - committed = commit; - } + commit = resok->committed; + np->n_fattr = resok->file_wcc->after; - if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) - { - bcopy((void) datareply, (void) nmp->nm_verf, NFSX_V3WRITEVERF); - nmp->nm_flag |= NFSMNT_HASWRITEVERF; - } - else if (bcmp((void) datareply, (void) nmp->nm_verf, NFSX_V3WRITEVERF)) - { - //*must_commit = 1; - bcopy((void) datareply, (void) nmp->nm_verf, NFSX_V3WRITEVERF); - } - } - else - { - nfsm_loadattr(vp, NULL); - } + /* Return the lowest committment level obtained by any of the RPCs. */ - if (wccflag) - { - VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime; - } + if (committed == NFSV3WRITE_FILESYNC) + { + committed = commit; + } + else if (committed == NFSV3WRITE_DATASYNC && + commit == NFSV3WRITE_UNSTABLE) + { + committed = commit; + } - tsiz -= len; + if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) + { + bcopy((void) resok->verf, (void) nmp->nm_verf, NFSX_V3WRITEVERF); + nmp->nm_flag |= NFSMNT_HASWRITEVERF; + } + else if (strncmp((char) resok->verf, (char) nmp->nm_verf, NFSX_V3WRITEVERF)) + { + bcopy((void) resok->verf, (void) nmp->nm_verf, NFSX_V3WRITEVERF); } + np->n_mtime = np->n_fattr.nfsv3fa_mtime; + + nfs_semgive(nmp); + return writesize; + errout_with_semaphore: nfs_semgive(nmp); - return (error); + return error; } /* nfs file remove call @@ -555,147 +553,134 @@ errout_with_semaphore: * else * do the remove rpc */ +/**************************************************************************** + * Name: nfs_remove + * + * Description: Remove a file + * + ****************************************************************************/ -int nfs_remove(void *v) +int nfs_remove(struct inode *mountpt, const char *relpath) //done { - struct vop_remove_args *ap = v; - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct componentname *cnp = ap->a_cnp; - struct nfsnode *np = VTONFS(vp); + struct nsfmount *nmp; + struct nfsnode *np; + void *datreply; + struct REMOVE3args *remove; + struct REMOVE3resok resok; int error = 0; - struct vattr vattr; - if (np->n_type == NDIR) - { - error = EPERM; - goto errout_with_semaphore; - } + /* Sanity checks */ - /* Do the rpc */ + DEBUGASSERT(mountpt && mountpt->i_private); - error = nfs_removerpc(dvp, cnp->cn_nameptr, - cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); + /* Get the mountpoint private data from the inode structure */ - /* Kludge City: If the first reply to the remove rpc is lost.. - * the reply to the retransmitted request will be ENOENT - * since the file was in fact removed - * Therefore, we cheat and return success. - */ + nmp = (struct nfsmount *)mountpt->i_private; + np = nmp->nm_head; - if (error == ENOENT) - { - error = 0; - } + /* Check if the mount is still healthy */ - NFS_INVALIDATE_ATTRCACHE(np); + nfs_semtake(nmp); + error = fat_checkmount(nmp); + if (error == 0) + { + /* If the file is open, the correct behavior is to remove the file + * name, but to keep the file cluster chain in place until the last + * open reference to the file is closed. + */ - /* VN_KNOTE(vp, NOTE_DELETE); - VN_KNOTE(dvp, NOTE_WRITE);*/ + /* Remove the file */ -errout_with_semaphore: - nfs_semgive(nmp); - return (error); -} + if (np->n_type != NFREG) + { + error = EPERM; + goto errout_with_semaphore; + } -/* Nfs remove rpc, called from nfs_remove() and nfs_removeit(). */ + /* Do the rpc */ -int -nfs_removerpc(struct vnode *dvp, char *name, int namelen, struct ucred *cred, - struct proc *proc) -{ - struct nfsm_info info; - uint32_t *tl; - int32_t t1; - caddr_t cp2; - int error = 0, wccflag = NFSV3_WCCRATTR; + nfsstats.rpccnt[NFSPROC_REMOVE]++; + remove->dir = nmp->nm_fh; + remove->name = relpath; - info.nmi_v3 = NFS_ISV3(dvp); + error = nfs_request(nmp, NFSPROC_REMOVE, remove, datareply); - nfsstats.rpccnt[NFSPROC_REMOVE]++; - nfsm_strtom(name, namelen, NFS_MAXNAMLEN); + /* Kludge City: If the first reply to the remove rpc is lost.. + * the reply to the retransmitted request will be ENOENT + * since the file was in fact removed + * Therefore, we cheat and return success. + */ - error = nfs_request(dvp, NFSPROC_REMOVE, &info); - if (info.nmi_v3) - nfsm_wcc_data(dvp, wccflag); + if (error == ENOENT) + { + error = 0; + } -nfsmout: - VTONFS(dvp)->n_flag |= NMODIFIED; - if (!wccflag) - NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp)); - return error; -} + if (error) + { + goto errout_with_semaphore; + } -/* nfs file rename call */ + resok = (struct REMOVE3resok *)datareply; + np->n_fattr = resok->dir_wcc->after; + np->n_flag |= NMODIFIED; + } + NFS_INVALIDATE_ATTRCACHE(np); -int nfs_rename(void *v) -{ - struct vop_rename_args *ap = v; - struct vnode *fvp = ap->a_fvp; - struct vnode *tvp = ap->a_tvp; - struct vnode *fdvp = ap->a_fdvp; - struct vnode *tdvp = ap->a_tdvp; - struct componentname *tcnp = ap->a_tcnp; - struct componentname *fcnp = ap->a_fcnp; - int error; +errout_with_semaphore: + nfs_semgive(nmp); + return error; +} -#ifdef DIAGNOSTIC - if ((tcnp->cn_flags & HASBUF) == 0 || (fcnp->cn_flags & HASBUF) == 0) - panic("nfs_rename: no name"); -#endif +/**************************************************************************** + * Name: nfs_rename + * + * Description: Rename a file or directory + * + ****************************************************************************/ - /* Check for cross-device rename */ +int nfs_rename(struct inode *mountpt, const char *oldrelpath, + const char *newrelpath) +{ + struct nsfmount *nmp; + struct nfsnode *np; + void *datreply; + struct RENAME3args *rename; + struct RENAME3resok resok; + int error = 0; - if ((fvp->v_mount != tdvp->v_mount) || - (tvp && (fvp->v_mount != tvp->v_mount))) - { - error = EXDEV; - goto out; - } + /* Sanity checks */ - /* If the tvp exists and is in use, sillyrename it before doing the - * rename of the new file over it. - */ + DEBUGASSERT(mountpt && mountpt->i_private); - if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && - tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) - { - VN_KNOTE(tvp, NOTE_DELETE); - vrele(tvp); - tvp = NULL; - } + /* Get the mountpoint private data from the inode structure */ - error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, - tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, - tcnp->cn_proc); + nmp = (struct nfsmount *)mountpt->i_private; + np = nmp->nm_head; - VN_KNOTE(fdvp, NOTE_WRITE); - VN_KNOTE(tdvp, NOTE_WRITE); + /* Check if the mount is still healthy */ - if (fvp->v_type == VDIR) + nfs_semtake(nmp); + error = nfs_checkmount(nmp); + if (error != 0) { - if (tvp != NULL && tvp->v_type == VDIR) - cache_purge(tdvp); - cache_purge(fdvp); + goto errout_with_semaphore; } -out: - if (tdvp == tvp) - { - vrele(tdvp); - } - else + if (np->nfsv3_type != NFREG && np->nfsv3_type != NFDIR) { - vput(tdvp); + fdbg("open eacces typ=%d\n", np->nfsv3_type); + error= -EACCES; + goto errout_with_semaphore; } - if (tvp) - { - vput(tvp); - } + nfsstats.rpccnt[NFSPROC_RENAME]++; + rename->from->dir = nmp->nm_fh; + rename->from->name = oldrelpath; + rename->to->dir = nmp->nm_fh; + rename->to->name = oldrelpath; - vrele(fdvp); - vrele(fvp); + error = nfs_request(fdvp, NFSPROC_RENAME, rename, datareply); /* Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. */ @@ -704,100 +689,50 @@ out: error = 0; } - return error; -} - -/* nfs file rename rpc called from nfs_remove() above */ - -int -nfs_renameit(struct vnode *sdvp, struct componentname *scnp, - struct sillyrename *sp) -{ - return nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, - sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, - curproc); -} - -/* Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). */ - -int -nfs_renamerpc(struct vnode *fdvp, char *fnameptr, int fnamelen, - struct vnode *tdvp, char *tnameptr, int tnamelen) -{ - struct nfsm_info info; - uint32_t *tl; - int32_t t1; - caddr_t cp2; - int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; - - info.nmi_v3 = NFS_ISV3(fdvp); - - nfsstats.rpccnt[NFSPROC_RENAME]++; - info.nmi_mb = info.nmi_mreq = nfsm_reqhead((NFSX_FH(info.nmi_v3) + - NFSX_UNSIGNED) * 2 + - nfsm_rndup(fnamelen) + - nfsm_rndup(tnamelen)); - nfsm_fhtom(&info, fdvp, info.nmi_v3); - nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); - nfsm_fhtom(&info, tdvp, info.nmi_v3); - nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); - - error = nfs_request(fdvp, NFSPROC_RENAME, &info); - if (info.nmi_v3) - { - nfsm_wcc_data(fdvp, fwccflag); - nfsm_wcc_data(tdvp, twccflag); - } - -nfsmout: - VTONFS(fdvp)->n_flag |= NMODIFIED; - VTONFS(tdvp)->n_flag |= NMODIFIED; - - if (!fwccflag) + if (error) { - NFS_INVALIDATE_ATTRCACHE(VTONFS(fdvp)); + goto errout_with_semaphore; } - if (!twccflag) - { - NFS_INVALIDATE_ATTRCACHE(VTONFS(tdvp)); - } + resok = (struct RENAME3resok *) datareply; + np->n_fattr = resok->todir_wcc->after + np->n_flag |= NMODIFIED; + NFS_INVALIDATE_ATTRCACHE(np); - return error; +errout_with_semaphore: + nfs_semgive(nmp); + return error; } -/* nfs make dir call */ +/**************************************************************************** + * Name: nfs_mkdir + * + * Description: Create a directory + * + ****************************************************************************/ int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) { - //struct vnode *dvp = ap->a_dvp; struct nfsv3_sattr *vap; + struct nfsv3_sattr *sp; struct nfsmount *nmp; struct nfsnode *np; - struct componentname *cnp = ap->a_cnp; - struct nfsv3_sattr *sp; - int info_v3; + struct MKDIR3args *mkdir; + struct MKDIR3resok resok; void *datareply; - //struct nfsm_info info; - //uint32_t *tl; - //int32_t t1; int len; struct nfsnode *npL; - struct file *newfilep ; - //caddr_t cp2; - int error = 0, wccflag = NFSV3_WCCRATTR; - int gotvp = 0; + int error = 0; - /* Sanity checks */ + /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ - nmp = mountpt->i_private; + nmp = (struct nfsmount*) mountpt->i_private; np = nmp->nm_head; vap = np->n_fattr; - info_v3 = (nmp->nm_flag & NFSMNT_NFSV3); /* Check if the mount is still healthy */ @@ -809,6 +744,8 @@ int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) } nfsstats.rpccnt[NFSPROC_MKDIR]++; + mkdir->dir = nmp->nm_fh; + mkdir->name = relpath; sp->sa_modetrue = nfs_true; sp->sa_mode = txdr_unsigned(vap->sa_mode); @@ -821,37 +758,18 @@ int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) txdr_nfsv3time(&vap->sa_atime, &sp->sa_atime); txdr_nfsv3time(&vap->sa_mtime, &sp->sa_mtime); - error = nfs_request(nmp, NFSPROC_MKDIR, datareply); - - -nfsmout: - nmp->n_flag |= NMODIFIED; - if (!wccflag) - { - NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp)); - } + mkdir->attributes = sp; + error = nfs_request(nmp, NFSPROC_MKDIR, mkdir, datareply); if (error) { - if (newvp) - { - vrele(newvp); - } - } - else - { - VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); - if (cnp->cn_flags & MAKEENTRY) - { - nfs_cache_enter(dvp, newvp, cnp); - } - - *ap->a_vpp = newvp; + goto errout_with_semaphore; } - return error; + nmp->n_flag |= NMODIFIED; + NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp)); - errout_with_semaphore: +errout_with_semaphore: nfs_semgive(nmp); return error; } @@ -1203,9 +1121,9 @@ int nfs_print(struct file *filep) //struct vnode *vp = ap->a_vp; struct nfsnode *np = VTONFS(filep); - printf("tag VT_NFS, fileid %ld fsid 0x%lx", - np->n_fattr.nfsv3fa_fileid, np->n_fattr.nfsv3fa_fsid); - printf("\n"); + nvdbg("tag VT_NFS, fileid %ld fsid 0x%lx", + np->n_fattr.nfsv3fa_fileid, np->n_fattr.nfsv3fa_fsid); + nvdbg("\n"); return 0; } */ @@ -1488,7 +1406,7 @@ void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) //done if (nmp->nm_sotype == SOCK_DGRAM) while (nfs_connect(nmp)) { - printf("nfs_args: retrying connect\n"); + nvdbg("nfs_args: retrying connect\n"); } } } @@ -1504,12 +1422,11 @@ void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) //done * ****************************************************************************/ -int nfs_mount(struct inode *blkdriver, const char *path, void *data, void **handle) //done +int nfs_mount(struct inode *blkdriver, void *data, void **handle) //done { int error; struct nfs_args args; struct sockaddr *nam; - char pth[90]; nfsfh_t nfh[NFSX_V3FHMAX]; bcopy(data, &args, sizeof(args.version)); @@ -1556,8 +1473,6 @@ int nfs_mount(struct inode *blkdriver, const char *path, void *data, void **hand } bcopy(args.fh, nfh, args.fhsize); - memset(&pth[90], 0, sizeof(*pth[90])); - bcopy(path, pth, 90 - 1); bcopy(args.addr, nam, sizeof(args.addr)); args.fh = nfh; error = mountnfs(&args, blkdriver, nam); @@ -1630,7 +1545,7 @@ int mountnfs(struct nfs_args *argp, struct inode *blkdriver, memmove(nmp->nm_fh, argp->fh, argp->fhsize); //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); + // bcopy(pth, nmp->nm_mntonname, 90); //memmove(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp)); nmp->nm_nam = nam; nfs_decode_args(nmp, argp); @@ -1777,9 +1692,9 @@ int nfs_sync(struct file *filep) //falta /* Check if the has been modified in any way */ if ((np->n_flag & NMODIFIED) != 0) - { - error = VOP_FSYNC(vp, cred, waitfor, p); /////////////////////////////// - } + { + error = VOP_FSYNC(vp, cred, waitfor, p); /////////////////////////////// + } return allerror; diff --git a/nuttx/fs/nfs/rpc.h b/nuttx/fs/nfs/rpc.h index 6e1d9d056..39b2040c2 100644 --- a/nuttx/fs/nfs/rpc.h +++ b/nuttx/fs/nfs/rpc.h @@ -144,6 +144,7 @@ struct rpc_call uint32_t rp_prog; /* program */ uint32_t rp_vers; /* version */ uint32_t rp_proc; /* procedure */ + void *data; struct rpc_auth_info rpc_auth; struct auth_unix rpc_unix; struct rpc_auth_info rpc_verf; @@ -248,7 +249,7 @@ int rpcclnt_connect(struct rpcclnt *); int rpcclnt_reconnect(struct rpctask *); void rpcclnt_disconnect(struct rpcclnt *); void rpcclnt_safedisconnect(struct rpcclnt *); -int rpcclnt_request(struct rpcclnt *, int, struct rpc_reply *); +int rpcclnt_request(struct rpcclnt *, int, struct rpc_reply *, void *); int rpcclnt_cancelreqs(struct rpcclnt *); #endif /* _RPCCLNT_H_ */ diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c index 0463e74da..7f54c6965 100644 --- a/nuttx/fs/nfs/rpc_clnt.c +++ b/nuttx/fs/nfs/rpc_clnt.c @@ -41,10 +41,10 @@ * * Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of * California. All rights reserved. - * + * * This code is derived from software contributed to Berkeley by Rick Macklem at * The University of Guelph. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -58,7 +58,7 @@ * name of the University nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -194,7 +194,7 @@ struct rpc_reply *replymsg; /* Queue head for rpctask's */ static dq_queue_t *rpctask_q; -//struct callout_handle rpcclnt_timer_handle; +//struct callout_handle rpcclnt_timer_handle; /**************************************************************************** * Private Function Prototypes @@ -217,7 +217,7 @@ 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, int, struct rpc_call *); +static int rpcclnt_buildheader(struct rpcclnt *, int, int, void *, struct rpc_call *); /**************************************************************************** * Private Functions @@ -246,27 +246,40 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, struct rpc_call *call, { RPC_RETURN(EINTR); } + if ((so = rep->r_rpcclnt->rc_so) == NULL) { rep->r_flags |= TASK_MUSTRESEND; RPC_RETURN(0); } + rep->r_flags &= ~TASK_MUSTRESEND; soflags = rep->r_rpcclnt->rc_soflags; } else - soflags = so->s_flags; + { + soflags = so->s_flags; + } + #ifdef CONFIG_NFS_TCPIP if ((soflags & PR_CONNREQUIRED)) - sendnam = NULL; + { + sendnam = NULL; + { else #endif - sendnam = nam; + { + sendnam = nam; + } if (so->s_type == SOCK_SEQPACKET) - flags = MSG_EOR; + { + flags = MSG_EOR; + } else - flags = 0; + { + flags = 0; + } error = psock_sendto(so, call, sizeof(*call), flags, sendnam, sizeof(*sendnam)); @@ -275,25 +288,32 @@ rpcclnt_send(struct socket *so, struct sockaddr *nam, struct rpc_call *call, { if (rep != NULL) { - printf("rpc send error %d for service %s\n", error, - rep->r_rpcclnt->rc_prog->prog_name); - /* - * Deal with errors for the client side. - */ + ndbg("rpc send error %d for service %s\n", error, + rep->r_rpcclnt->rc_prog->prog_name); + + /* Deal with errors for the client side. */ + if (rep->r_flags & TASK_SOFTTERM) - error = EINTR; + { + error = EINTR; + } else - rep->r_flags |= TASK_MUSTRESEND; + { + rep->r_flags |= TASK_MUSTRESEND; + } } else - printf("rpc service send error %d\n", error); + { + ndbg("rpc service send error %d\n", error); + } + + /* Handle any recoverable (soft) socket errors here. */ - /* - * Handle any recoverable (soft) socket errors here. - */ if (error != EINTR && error != ERESTART && error != EWOULDBLOCK && error != EPIPE) - error = 0; + { + error = 0; + } } RPC_RETURN(error); @@ -331,8 +351,12 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, { error = rpcclnt_sndlock(&rep->r_rpcclnt->rc_flag, rep); if (error != 0) - return (error); + { + return error; + } + tryagain: + /* Check for fatal errors and resending request. * * Ugh: If a reconnect attempt just happened, rc_so would @@ -343,8 +367,9 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, if (rep->r_flags & TASK_SOFTTERM) { rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - return (EINTR); + return EINTR; } + so = rep->r_rpcclnt->rc_so; if (so == NULL) { @@ -352,8 +377,9 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, if (error) { rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - return (error); + return error; } + goto tryagain; } while (rep->r_flags & TASK_MUSTRESEND) @@ -366,8 +392,9 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, (error = rpcclnt_reconnect(rep)) != 0) { rpcclnt_sndunlock(&rep->r_rpcclnt->rc_flag); - return (error); + return error; } + goto tryagain; } } @@ -382,14 +409,16 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, &rcvflg, rep->r_rpcclnt->rc_name, sizeof(*rep->r_rpcclnt->rc_name)); if (error == EWOULDBLOCK && rep && (rep->r_flags & TASK_SOFTTERM)) - RPC_RETURN(EINTR); + { + RPC_RETURN(EINTR); + } } while (error == EWOULDBLOCK); if (error == 0) { - printf("short receive from rpc server %s\n", - rep->r_rpcclnt->rc_prog->prog_name); + ndbg("short receive from rpc server %s\n", + rep->r_rpcclnt->rc_prog->prog_name); error = EPIPE; } @@ -402,9 +431,9 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, if (len > RPC_MAXPACKET) { - printf("%s (%d) from rpc server %s\n", - "impossible packet length", - len, rep->r_rpcclnt->rc_prog->prog_name); + ndbg("%s (%d) from rpc server %s\n", + "impossible packet length", + len, rep->r_rpcclnt->rc_prog->prog_name); error = EFBIG; goto errout; } @@ -419,14 +448,15 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, if (error == 0) { - printf("short receive from rpc server %s\n", - rep->r_rpcclnt->rc_prog->prog_name); + ndbg("short receive from rpc server %s\n", + rep->r_rpcclnt->rc_prog->prog_name); error = EPIPE; } if (error != 0) - goto errout; - + { + goto errout; + } } else { @@ -447,36 +477,51 @@ static int rpcclnt_receive(struct rpctask *rep, struct sockaddr *aname, { if (rep->r_flags & TASK_SOFTTERM) { - return (EINTR); + return EINTR; } } } while (error == EWOULDBLOCK || (!error)); if ((rcvflg & MSG_EOR) == 0) - printf("Egad!!\n"); + { + ndbg("Egad!!\n"); + } + if (error == 0) - error = EPIPE; + { + error = EPIPE; + } } errout: if (error != 0 && error != EINTR && error != ERESTART) { if (error != EPIPE) - printf("receive error %d from rpc server %s\n", + { + ndbg("receive error %d from rpc server %s\n", error, rep->r_rpcclnt->rc_prog->prog_name); + } + error = rpcclnt_sndlock(&rep->r_rpcclnt->rc_flag, rep); if (error == 0) - error = rpcclnt_reconnect(rep); + { + error = rpcclnt_reconnect(rep); + } + if (error == 0) - goto tryagain; + { + goto tryagain; + } } } else { #endif if ((so = rep->r_rpcclnt->rc_so) == NULL) - RPC_RETURN(EACCES); + { + RPC_RETURN(EACCES); + } do { @@ -529,9 +574,11 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, #ifdef CONFIG_NFS_TCPIP error = rpcclnt_rcvlock(myrep); if (error) - return (error); + { + return error; + } #endif - /* + /* * Get the next Rpc reply off the socket */ error = rpcclnt_receive(myrep, nam, reply, call); @@ -549,8 +596,11 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, if (RPCIGNORE_SOERROR(rpc->rc_soflags, error)) { if (myrep->r_flags & TASK_GETONEREP) - RPC_RETURN(0); - dbg("ingoring routing error on connectionless protocol."); + { + RPC_RETURN(0); + } + + ndbg("ingoring routing error on connectionless protocol."); continue; } RPC_RETURN(error); @@ -563,7 +613,10 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, { rpcstats.rpcinvalid++; if (myrep->r_flags & TASK_GETONEREP) - RPC_RETURN(0); + { + RPC_RETURN(0); + } + continue; } @@ -586,7 +639,9 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, (RPC_CWNDSCALE * RPC_CWNDSCALE + (rpc->rc_cwnd >> 1)) / rpc->rc_cwnd; if (rpc->rc_cwnd > RPC_MAXCWND) - rpc->rc_cwnd = RPC_MAXCWND; + { + rpc->rc_cwnd = RPC_MAXCWND; + } } rep->r_flags &= ~TASK_SENT; @@ -610,10 +665,14 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, t1 -= (RPC_SRTT(rpc, rep) >> 3); RPC_SRTT(rpc, rep) += t1; if (t1 < 0) - t1 = -t1; + { + t1 = -t1; + } + t1 -= (RPC_SDRTT(rpc, rep) >> 2); RPC_SDRTT(rpc, rep) += t1; } + rpc->rc_timeouts = 0; break; } @@ -632,8 +691,11 @@ rpcclnt_reply(struct rpctask *myrep, struct rpc_call *call, { RPC_RETURN(0); } + if (myrep->r_flags & TASK_GETONEREP) - RPC_RETURN(0); + { + RPC_RETURN(0); + } } } @@ -644,22 +706,32 @@ rpcclnt_sigintr( struct rpcclnt *rpc, struct rpctask *task, cthread_t *td) struct proc *p; sigset_t tmpset; - if (rpc == NULL) - return EFAULT; + if (rpc == NULL) + { + return EFAULT; + } - if (ISSET(rpc->rc_flag, RPCCLNT_REDIRECT)) /* Should signal? */ - return (0); + if (ISSET(rpc->rc_flag, RPCCLNT_REDIRECT)) + { + return 0; + } /* XXX deal with forced unmounts */ if (task && ISSET(task->r_flags, TASK_SOFTTERM)) - RPC_RETURN(EINTR); + { + RPC_RETURN(EINTR); + } if (!ISSET(rpc->rc_flag, RPCCLNT_INT)) - RPC_RETURN(0); + { + RPC_RETURN(0); + } if (td == NULL) - return (0); + { + return 0; + } p = cthread_proc(td); @@ -669,11 +741,13 @@ rpcclnt_sigintr( struct rpcclnt *rpc, struct rpctask *task, cthread_t *td) mtx_lock(&p->p_sigacts->ps_mtx); SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); mtx_unlock(&p->p_sigacts->ps_mtx); + if (SIGNOTEMPTY(p->p_siglist) && RPCCLNTINT_SIGMASK(tmpset)) { PROC_UNLOCK(p); RPC_RETURN(EINTR); } + PROC_UNLOCK(p); RPC_RETURN(0); } @@ -696,7 +770,10 @@ static int rpcclnt_sndlock(int *flagp, struct rpctask *task) while (*flagp & RPCCLNT_SNDLOCK) { if (rpcclnt_sigintr(task->r_rpcclnt, task, p)) - return (EINTR); + { + return EINTR; + } + *flagp |= RPCCLNT_WANTSND; if (slpflag == PCATCH) { @@ -706,7 +783,7 @@ static int rpcclnt_sndlock(int *flagp, struct rpctask *task) } *flagp |= RPCCLNT_SNDLOCK; - return (0); + return 0; } /* Unlock the stream socket for others. */ @@ -731,14 +808,21 @@ static int rpcclnt_rcvlock(struct rpctask *task) int slpflag, slptimeo = 0; if (*flagp & RPCCLNT_INT) - slpflag = PCATCH; + { + slpflag = PCATCH; + } else - slpflag = 0; + { + slpflag = 0; + } while (*flagp & RPCCLNT_RCVLOCK) { if (rpcclnt_sigintr(task->r_rpcclnt, task, task->r_td)) - return (EINTR); + { + return EINTR; + } + *flagp |= RPCCLNT_WANTRCV; tsleep((caddr_t) flagp, slpflag | (PZERO - 1), "rpcrcvlk", slptimeo); if (slpflag == PCATCH) @@ -749,7 +833,7 @@ static int rpcclnt_rcvlock(struct rpctask *task) } *flagp |= RPCCLNT_RCVLOCK; - return (0); + return 0; } /* Unlock the stream socket for others. */ @@ -774,9 +858,11 @@ static uint32_t rpcclnt_proct(struct rpcclnt *rpc, uint32_t procid) { if (rpc->rc_proctlen != 0 && rpc->rc_proct != NULL && procid < rpc->rc_proctlen) - return (rpc->rc_proct[procid]); + { + return rpc->rc_proct[procid]; + } - return (0); + return 0; } static void rpcclnt_softterm(struct rpctask *task) @@ -797,7 +883,10 @@ void rpcclnt_init(void) { rpcclnt_ticks = (CLOCKS_PER_SEC * RPC_TICKINTVL + 500) / 1000; if (rpcclnt_ticks < 1) - rpcclnt_ticks = 1; + { + rpcclnt_ticks = 1; + } + rpcstats.rpcretries = 0; rpcstats.rpcrequests = 0; rpcstats.rpctimeouts = 0; @@ -822,7 +911,7 @@ void rpcclnt_init(void) rpcclnt_timer(NULL, callmgs); - printf("rpc initialed"); + nvdbg("rpc initialed"); return; } @@ -830,9 +919,8 @@ void rpcclnt_init(void) void rpcclnt_uninit(void) { - printf("uninit"); - untimeout(rpcclnt_timer, (void *)NULL, rpcclnt_timer_handle); - + nvdbg("uninit"); + untimeout(rpcclnt_timer, (void *)NULL, rpcclnt_timer_handle); } */ @@ -849,7 +937,8 @@ int rpcclnt_connect(struct rpcclnt *rpc) struct timeval *tv = NULL; uint16_t tport; - /* create the socket */ + /* Create the socket */ + rpc->rc_so = NULL; saddr = rpc->rc_name; rpc->rc_sotype = SOCK_DGRAM; @@ -859,7 +948,7 @@ int rpcclnt_connect(struct rpcclnt *rpc) if (error != 0) { - printf("error %d in psock_socket()", error); + ndbg("error %d in psock_socket()", error); RPC_RETURN(error); } @@ -885,7 +974,7 @@ int rpcclnt_connect(struct rpcclnt *rpc) if (error) { - printf("bind failed\n"); + ndbg("bind failed\n"); goto bad; } @@ -962,7 +1051,9 @@ int rpcclnt_reconnect(struct rpctask *rep) while ((error = rpcclnt_connect(rpc)) != 0) { if (error == EINTR || error == ERESTART) - return (EINTR); + { + return EINTR; + } } /* Loop through outstanding request list and fix up all @@ -973,9 +1064,11 @@ int rpcclnt_reconnect(struct rpctask *rep) rp = (struct rpctask *)rp->r_chain.blink) { if (rp->r_rpcclnt == rpc) - rp->r_flags |= TASK_MUSTRESEND; + { + rp->r_flags |= TASK_MUSTRESEND; + } } - return (0); + return 0; } void rpcclnt_disconnect(struct rpcclnt *rpc) @@ -1010,16 +1103,16 @@ void rpcclnt_safedisconnect(struct rpcclnt *rpc) * nfs_receive() to get reply - fills in reply (which should be initialized * prior to calling), which is valid when 0 is returned and is NEVER freed in * this function - * + * * always frees the request header, but NEVER frees 'mrest' - * + * * * note that reply->result_* are invalid unless reply->type == * RPC_MSGACCEPTED and reply->status == RPC_SUCCESS and that reply->verf_* * are invalid unless reply->type == RPC_MSGACCEPTED */ -int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) +int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply, void *datain) { struct rpc_call *call = NULL; struct rpc_reply *replysvr = NULL; @@ -1033,25 +1126,34 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) task->r_rpcclnt = rpc; task->r_procnum = procnum; - error = rpcclnt_buildheader(rpc, procnum, xid, call); + error = rpcclnt_buildheader(rpc, procnum, xid, datain, call); if (error) { - printf("building call header error"); + ndbg("building call header error"); goto rpcmout; } task->r_xid = fxdr_unsigned(uint32_t, xid); if (rpc->rc_flag & RPCCLNT_SOFT) - task->r_retry = rpc->rc_retry; + { + task->r_retry = rpc->rc_retry; + } else - task->r_retry = RPC_MAXREXMIT + 1; /* past clip limit */ + { + task->r_retry = RPC_MAXREXMIT + 1; /* past clip limit */ + } + task->r_rtt = task->r_rexmit = 0; if (rpcclnt_proct(rpc, procnum) > 0) - task->r_flags = TASK_TIMING; + { + task->r_flags = TASK_TIMING; + } else - task->r_flags = 0; + { + task->r_flags = 0; + } /* Do the client side RPC. */ @@ -1072,10 +1174,11 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) (rpc->rc_flag & RPCCLNT_DUMBTIMR) || rpc->rc_sent < rpc->rc_cwnd)) { - #ifdef CONFIG_NFS_TCPIP if (rpc->rc_soflags & PR_CONNREQUIRED) - error = rpcclnt_sndlock(&rpc->rc_flag, task); + { + error = rpcclnt_sndlock(&rpc->rc_flag, task); + } #endif if (error == 0) @@ -1084,7 +1187,9 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) #ifdef CONFIG_NFS_TCPIP if (rpc->rc_soflags & PR_CONNREQUIRED) - rpcclnt_sndunlock(&rpc->rc_flag); + { + rpcclnt_sndunlock(&rpc->rc_flag); + } #endif } if (error == 0 && (task->r_flags & TASK_MUSTRESEND) == 0) @@ -1101,7 +1206,9 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) /* Wait for the reply from our send. */ if (error == 0 || error == EPIPE) - error = rpcclnt_reply(task, call, replysvr); + { + error = rpcclnt_reply(task, call, replysvr); + } /* RPC done, unlink the request. */ @@ -1116,7 +1223,9 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) } if (error != 0) - goto rpcmout; + { + goto rpcmout; + } /* Break down the rpc header and check if ok */ @@ -1131,14 +1240,16 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) fxdr_unsigned(uint32_t, replysvr->stat.mismatch_info.low); reply->stat.mismatch_info.high = fxdr_unsigned(uint32_t, replysvr->stat.mismatch_info.high); - printf("RPC_MSGDENIED: RPC_MISMATCH error"); + ndbg("RPC_MSGDENIED: RPC_MISMATCH error"); error = EOPNOTSUPP; break; + case RPC_AUTHERR: reply->stat.autherr = fxdr_unsigned(uint32_t, replysvr->stat.autherr); - printf("RPC_MSGDENIED: RPC_AUTHERR error"); + ndbg("RPC_MSGDENIED: RPC_AUTHERR error"); error = EACCES; break; + default: error = EOPNOTSUPP; break; @@ -1160,7 +1271,7 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) if (reply->stat.status == RPC_SUCCESS) { - printf("RPC_SUCCESS"); + nvdbg("RPC_SUCCESS"); reply->stat.where = replysvr->stat.where; } else if (reply->stat.status == RPC_PROGMISMATCH) @@ -1169,7 +1280,7 @@ int rpcclnt_request(struct rpcclnt *rpc, int procnum, struct rpc_reply *reply) fxdr_unsigned(uint32_t, replysvr->stat.mismatch_info.low); reply->stat.mismatch_info.high = fxdr_unsigned(uint32_t, replysvr->stat.mismatch_info.high); - printf("RPC_MSGACCEPTED: RPC_PROGMISMATCH error"); + ndbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error"); error = EOPNOTSUPP; /* XXXMARIUS */ } else if (reply->stat.status > 5) @@ -1199,20 +1310,36 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) { rpc = rep->r_rpcclnt; if (rep->r_flags & TASK_SOFTTERM) - continue; + { + continue; + } + if (rep->r_rtt >= 0) { rep->r_rtt++; if (rpc->rc_flag & RPCCLNT_DUMBTIMR) - timeo = rpc->rc_timeo; + { + timeo = rpc->rc_timeo; + } else - timeo = RPC_RTO(rpc, rpcclnt_proct(rep->r_rpcclnt, rep->r_procnum)); + { + timeo = RPC_RTO(rpc, rpcclnt_proct(rep->r_rpcclnt, rep->r_procnum)); + } + if (rpc->rc_timeouts > 0) - timeo *= rpcclnt_backoff[rpc->rc_timeouts - 1]; + { + timeo *= rpcclnt_backoff[rpc->rc_timeouts - 1]; + } + if (rep->r_rtt <= timeo) - continue; + { + continue; + } + if (rpc->rc_timeouts < 8) - rpc->rc_timeouts++; + { + rpc->rc_timeouts++; + } } /* Check for server not responding */ @@ -1220,23 +1347,30 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) if ((rep->r_flags & TASK_TPRINTFMSG) == 0 && rep->r_rexmit > rpc->rc_deadthresh) { - printf("Server is not responding"); + ndbg("Server is not responding"); rep->r_flags |= TASK_TPRINTFMSG; } + if (rep->r_rexmit >= rep->r_retry) { /* too many */ rpcstats.rpctimeouts++; rep->r_flags |= TASK_SOFTTERM; continue; } + if (rpc->rc_sotype != SOCK_DGRAM) { if (++rep->r_rexmit > RPC_MAXREXMIT) - rep->r_rexmit = RPC_MAXREXMIT; + { + rep->r_rexmit = RPC_MAXREXMIT; + } continue; } + if ((so = rpc->rc_so) == NULL) - continue; + { + continue; + } /* If there is enough space and the window allows.. Resend it * Set r_rtt to -1 in case we fail to send it now. @@ -1248,11 +1382,15 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) { if ((rpc->rc_flag & RPCCLNT_NOCONN) == 0) - error = psock_sendto(so, call, sizeof(*call), 0, NULL, 0); + { + error = psock_sendto(so, call, sizeof(*call), 0, NULL, 0); + } else - error = - psock_sendto(so, call, sizeof(*call), 0, rpc->rc_name, - sizeof(*rpc->rc_name)); + { + error = + psock_sendto(so, call, sizeof(*call), 0, rpc->rc_name, + sizeof(*rpc->rc_name)); + } if (!error) { @@ -1265,10 +1403,16 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) { rep->r_flags &= ~TASK_TIMING; if (++rep->r_rexmit > RPC_MAXREXMIT) - rep->r_rexmit = RPC_MAXREXMIT; + { + rep->r_rexmit = RPC_MAXREXMIT; + } + rpc->rc_cwnd >>= 1; if (rpc->rc_cwnd < RPC_CWNDSCALE) - rpc->rc_cwnd = RPC_CWNDSCALE; + { + rpc->rc_cwnd = RPC_CWNDSCALE; + } + rpcstats.rpcretries++; } else @@ -1276,6 +1420,7 @@ void rpcclnt_timer(void *arg, struct rpc_call *call) rep->r_flags |= TASK_SENT; rpc->rc_sent += RPC_CWNDSCALE; } + rep->r_rtt = 0; } } @@ -1287,7 +1432,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 *rc, int procid, - int xidp, struct rpc_call *call) + int xidp, void *datain, struct rpc_call *call) { struct timeval *tv = NULL; srand(time(NULL)); @@ -1317,6 +1462,7 @@ int rpcclnt_buildheader(struct rpcclnt *rc, int procid, call->rp_prog = txdr_unsigned(rc->rc_prog->prog_id); call->rp_vers = txdr_unsigned(rc->rc_prog->prog_version); call->rp_proc = txdr_unsigned(procid); + call->data = datain; /* rpc_auth part (auth_unix as root) */ @@ -1337,7 +1483,7 @@ int rpcclnt_buildheader(struct rpcclnt *rc, int procid, call->rpc_verf.authtype = 0; call->rpc_verf.authlen = 0; - return (0); + return 0; } int rpcclnt_cancelreqs(struct rpcclnt *rpc) @@ -1349,7 +1495,10 @@ int rpcclnt_cancelreqs(struct rpcclnt *rpc) task = (struct rpctask *)task->r_chain.flink) { if (rpc != task->r_rpcclnt || (task->r_flags & TASK_SOFTTERM)) - continue; + { + continue; + } + rpcclnt_softterm(task); } @@ -1359,12 +1508,17 @@ int rpcclnt_cancelreqs(struct rpcclnt *rpc) task = (struct rpctask *)task->r_chain.flink) { if (rpc == task->r_rpcclnt) - break; + { + break; + } } + if (task == NULL) - return (0); + { + return 0; + } } - return (EBUSY); + return EBUSY; } #endif |