NFS client update

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