mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
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:
parent
58a69e2d0e
commit
8105db36c1
8 changed files with 728 additions and 536 deletions
148
fs/nfs/nfs.h
148
fs/nfs/nfs.h
|
@ -73,9 +73,9 @@
|
|||
/* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with
|
||||
* broken NFS/ethernet drivers that won't work with anything bigger (Linux..)
|
||||
*/
|
||||
|
||||
#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */
|
||||
#define NFS_READDIRBLKSIZ 512 /* Size of read dir blocks. XXX */
|
||||
|
||||
#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */
|
||||
#define NFS_READDIRBLKSIZ 512 /* Size of read dir blocks. XXX */
|
||||
|
||||
/* Oddballs */
|
||||
|
||||
|
@ -102,17 +102,17 @@
|
|||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
|
||||
/* Flags for nfssvc() system call. */
|
||||
|
||||
#define NFSSVC_BIOD 0x002
|
||||
#define NFSSVC_NFSD 0x004
|
||||
#define NFSSVC_ADDSOCK 0x008
|
||||
#define NFSSVC_AUTHIN 0x010
|
||||
#define NFSSVC_GOTAUTH 0x040
|
||||
#define NFSSVC_BIOD 0x002
|
||||
#define NFSSVC_NFSD 0x004
|
||||
#define NFSSVC_ADDSOCK 0x008
|
||||
#define NFSSVC_AUTHIN 0x010
|
||||
#define NFSSVC_GOTAUTH 0x040
|
||||
#define NFSSVC_AUTHINFAIL 0x080
|
||||
#define NFSSVC_MNTD 0x100
|
||||
#define NFSSVC_MNTD 0x100
|
||||
|
||||
/* fs.nfs sysctl(3) identifiers */
|
||||
|
||||
|
@ -129,8 +129,7 @@
|
|||
#define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
|
||||
sigmask(SIGHUP)|sigmask(SIGQUIT))
|
||||
|
||||
/*
|
||||
* Socket errors ignored for connectionless sockets??
|
||||
/* Socket errors ignored for connectionless sockets??
|
||||
* For now, ignore them all
|
||||
*/
|
||||
|
||||
|
@ -316,7 +315,7 @@ struct nfssvc_sock
|
|||
int ns_solock; /* lock for connected socket */
|
||||
int ns_cc; /* actual chars queued */
|
||||
int ns_reclen; /* length of first queued record */
|
||||
uint32_t ns_sref; /* # of refs to this struct */
|
||||
uint32_t ns_sref; /* # of refs to this struct */
|
||||
};
|
||||
|
||||
/* One of these structures is allocated for each nfsd. */
|
||||
|
@ -324,19 +323,127 @@ struct nfssvc_sock
|
|||
struct nfsd
|
||||
{
|
||||
//TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* This structure is used by the server for describing each request. */
|
||||
|
||||
struct nfsrv_descript
|
||||
{
|
||||
unsigned int nd_procnum; /* RPC # */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_repstat; /* Reply status */
|
||||
uint32_t nd_retxid; /* Reply xid */
|
||||
unsigned int nd_procnum; /* RPC # */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_repstat; /* Reply status */
|
||||
uint32_t nd_retxid; /* Reply xid */
|
||||
};
|
||||
|
||||
/* NFS procedures args */
|
||||
|
||||
struct wcc_attr
|
||||
{
|
||||
nfsuint64 size;
|
||||
nfstime3 mtime;
|
||||
nfstime3 ctime;
|
||||
}
|
||||
|
||||
struct wcc_data
|
||||
{
|
||||
wcc_attr before;
|
||||
nfs_fattr after;
|
||||
};
|
||||
|
||||
struct diropargs3
|
||||
{
|
||||
nfsfh_t dir;
|
||||
const char name;
|
||||
};
|
||||
|
||||
struct CREATE3args
|
||||
{
|
||||
diropargs3 where;
|
||||
nfsv3_sattr how;
|
||||
};
|
||||
|
||||
struct CREATE3resok
|
||||
{
|
||||
const char handle;
|
||||
nfs_fattr attributes;
|
||||
wcc_data dir_wcc;
|
||||
};
|
||||
|
||||
struct READ3args
|
||||
{
|
||||
nfstype file;
|
||||
uint64_t offset;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct READ3resok
|
||||
{
|
||||
nfs_fattr file_attributes;
|
||||
uint32_t count;
|
||||
bool eof;
|
||||
const char data;
|
||||
};
|
||||
|
||||
enum stable_how
|
||||
{
|
||||
UNSTABLE = 0,
|
||||
DATA_SYNC = 1,
|
||||
FILE_SYNC = 2
|
||||
};
|
||||
|
||||
struct WRITE3args
|
||||
{
|
||||
nfstype file;
|
||||
uint64_t offset;
|
||||
uint32_t count;
|
||||
stable_how stable;
|
||||
const char data;
|
||||
};
|
||||
|
||||
struct WRITE3resok
|
||||
{
|
||||
wcc_data file_wcc;
|
||||
count3 count;
|
||||
stable_how committed;
|
||||
unsigned char verf;
|
||||
};
|
||||
|
||||
struct REMOVE3args
|
||||
{
|
||||
diropargs3 object;
|
||||
};
|
||||
|
||||
struct REMOVE3resok
|
||||
{
|
||||
wcc_data dir_wcc;
|
||||
};
|
||||
|
||||
struct RENAME3args
|
||||
{
|
||||
diropargs3 from;
|
||||
diropargs3 to;
|
||||
};
|
||||
|
||||
struct RENAME3resok
|
||||
{
|
||||
wcc_data fromdir_wcc;
|
||||
wcc_data todir_wcc;
|
||||
};
|
||||
|
||||
struct MKDIR3args
|
||||
{
|
||||
diropargs3 where;
|
||||
nfsv3_sattr attributes;
|
||||
};
|
||||
|
||||
struct MKDIR3resok
|
||||
{
|
||||
const char handle;
|
||||
nfs_fattr obj_attributes;
|
||||
wcc_data dir_wcc;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -352,6 +459,7 @@ extern struct pool nfs_node_pool;
|
|||
extern TAILQ_HEAD(nfsdhead, nfsd) nfsd_head;
|
||||
extern int nfsd_head_flag;
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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*/
|
||||
};
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue