NFS client update

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4605 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-04-14 00:27:44 +00:00
parent 58a69e2d0e
commit 8105db36c1
8 changed files with 728 additions and 536 deletions

View file

@ -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
****************************************************************************/

View file

@ -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*/
};

View file

@ -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. */

View file

@ -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. */

View file

@ -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 */

View file

@ -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)
{
nfsstats.rpccnt[NFSPROC_READ]++;
len = nmp->nm_rsize;
len = nmp->nm_rsize;
if (len < buflen)
{
error = EFBIG
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)
{
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);
tsiz -= retlen;
if (info_v3)
{
if (eof || retlen == 0)
{
tsiz = 0;
}
}
else if (retlen < len)
{
tsiz = 0;
}
}
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);
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;
error = -EFBIG
goto errout_with_semaphore;
}
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:
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)
/* 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;
goto errout_with_semaphore;
/* 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.
*/
/* 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);
/* VN_KNOTE(vp, NOTE_DELETE);
VN_KNOTE(dvp, NOTE_WRITE);*/
errout_with_semaphore:
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
nfs_removerpc(struct vnode *dvp, char *name, int namelen, struct ucred *cred,
struct proc *proc)
int nfs_rename(struct inode *mountpt, const char *oldrelpath,
const char *newrelpath)
{
struct nfsm_info info;
uint32_t *tl;
int32_t t1;
caddr_t cp2;
int error = 0, wccflag = NFSV3_WCCRATTR;
struct nsfmount *nmp;
struct nfsnode *np;
void *datreply;
struct RENAME3args *rename;
struct RENAME3resok resok;
int error = 0;
info.nmi_v3 = NFS_ISV3(dvp);
/* Sanity checks */
nfsstats.rpccnt[NFSPROC_REMOVE]++;
nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
DEBUGASSERT(mountpt && mountpt->i_private);
error = nfs_request(dvp, NFSPROC_REMOVE, &info);
if (info.nmi_v3)
nfsm_wcc_data(dvp, wccflag);
/* Get the mountpoint private data from the inode structure */
nfsmout:
VTONFS(dvp)->n_flag |= NMODIFIED;
if (!wccflag)
NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
return error;
}
nmp = (struct nfsmount *)mountpt->i_private;
np = nmp->nm_head;
/* nfs file rename call */
/* Check if the mount is still healthy */
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;
#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)))
nfs_semtake(nmp);
error = nfs_checkmount(nmp);
if (error != 0)
{
error = EXDEV;
goto out;
goto errout_with_semaphore;
}
/* If the tvp exists and is in use, sillyrename it before doing the
* 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))
if (np->nfsv3_type != NFREG && np->nfsv3_type != NFDIR)
{
VN_KNOTE(tvp, NOTE_DELETE);
vrele(tvp);
tvp = NULL;
fdbg("open eacces typ=%d\n", np->nfsv3_type);
error= -EACCES;
goto errout_with_semaphore;
}
error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
tcnp->cn_proc);
nfsstats.rpccnt[NFSPROC_RENAME]++;
rename->from->dir = nmp->nm_fh;
rename->from->name = oldrelpath;
rename->to->dir = nmp->nm_fh;
rename->to->name = oldrelpath;
VN_KNOTE(fdvp, NOTE_WRITE);
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);
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)
if (error)
{
nfsm_wcc_data(fdvp, fwccflag);
nfsm_wcc_data(tdvp, twccflag);
goto errout_with_semaphore;
}
nfsmout:
VTONFS(fdvp)->n_flag |= NMODIFIED;
VTONFS(tdvp)->n_flag |= NMODIFIED;
resok = (struct RENAME3resok *) datareply;
np->n_fattr = resok->todir_wcc->after
np->n_flag |= NMODIFIED;
NFS_INVALIDATE_ATTRCACHE(np);
if (!fwccflag)
{
NFS_INVALIDATE_ATTRCACHE(VTONFS(fdvp));
}
if (!twccflag)
{
NFS_INVALIDATE_ATTRCACHE(VTONFS(tdvp));
}
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;

View file

@ -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_ */

View file

@ -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