NFS client update

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4544 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-03-30 23:56:35 +00:00
parent defc29ea07
commit 0b4b277a58
4 changed files with 88 additions and 196 deletions

View File

@ -72,7 +72,6 @@ struct nfsmount
struct nfsnode *nm_head; /* A list to all files opened on this mountpoint */
bool nm_mounted; /* true: The file system is ready */
sem_t nm_sem; /* Used to assume thread-safe access */
nfstype nfsv3_type; /* File type */
int nm_numgrps; /* Max. size of groupslist */
nfsfh_t nm_fh; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */

View File

@ -115,6 +115,7 @@ 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 */
nfstype nfsv3_type; /* File type */
time_t n_attrstamp; /* Attr. cache timestamp */
struct timespec n_mtime; /* Prev modify time. */
time_t n_ctime; /* Prev create time. */
@ -129,7 +130,7 @@ struct nfsnode
union
{
struct timespec nf_mtim;
off_t nd_direof; /* Dir. EOF offset cache */
off_t nd_direoffset; /* Directory EOF offset cache */
} n_un2;
short n_fhsize; /* size in bytes, of fh */
short n_flag; /* Flag for locking.. */

View File

@ -155,7 +155,7 @@ nfs_open(FAR struct file *filep, FAR const char *relpath,
if (np->nfsv3_type != NFREG && np->nfsv3_type != NFDIR)
{
dbg("open eacces typ=%d\n", np->nfsv3_type);
fdbg("open eacces typ=%d\n", np->nfsv3_type);
return (EACCES);
}
@ -190,8 +190,11 @@ nfs_create(FAR struct file *filp, FAR const char *relpath,
/* Oops, not for me.. */
if (vap->va_type == VSOCK)
return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
if (np->nfsv3_type == VSOCK)
{
fdbg("open eacces type=%d\n", np->nfsv3_type);
return (EACCES);
}
if (vap->va_vaflags & VA_EXCLUSIVE)
fmode |= O_EXCL;
@ -209,7 +212,7 @@ again:
error = nfs_request(in, NFSPROC_CREATE);
if (!error)
{
nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp);
nfsm_mtofh(dvp, newvp, info_v3, gotvp);
if (!gotvp)
{
if (newvp)
@ -217,11 +220,6 @@ again:
vrele(newvp);
newvp = NULL;
}
error = nfs_lookitup(dvp, cnp->cn_nameptr,
cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc,
&np);
if (!error)
newvp = NFSTOV(np);
}
}
if (info_v3)
@ -230,7 +228,7 @@ again:
nfsmout:
if (error)
{
if (info.nmi_v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP)
if (info_v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP)
{
fmode &= ~O_EXCL;
goto again;
@ -238,7 +236,7 @@ nfsmout:
if (newvp)
vrele(newvp);
}
else if (info.nmi_v3 && (fmode & O_EXCL))
else if (info_v3 && (fmode & O_EXCL))
error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
if (!error)
{
@ -547,12 +545,9 @@ nfs_removerpc(struct vnode *dvp, char *name, int namelen, struct ucred *cred,
nfsm_fhtom(&info, dvp, info.nmi_v3);
nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
info.nmi_procp = proc;
info.nmi_cred = cred;
error = nfs_request(dvp, NFSPROC_REMOVE, &info);
if (info.nmi_v3)
nfsm_wcc_data(dvp, wccflag);
m_freem(info.nmi_mrep);
nfsmout:
VTONFS(dvp)->n_flag |= NMODIFIED;
@ -725,12 +720,6 @@ int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
nfsstats.rpccnt[NFSPROC_MKDIR]++;
if (info_v3)
{
nfsm_v3attrbuild(&info.nmi_mb, vap, 0);
}
else
{
sp->sa_modetrue = nfs_true;
sp->sa_mode = txdr_unsigned(vap->sa_mode);
sp->sa_uid = nfs_xdrneg1;
@ -738,18 +727,18 @@ int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
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);
}
error = nfs_request(dvp, NFSPROC_MKDIR, &info);
error = nfs_request(nmp, NFSPROC_MKDIR, &info);
if (!error)
nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp);
if (info.nmi_v3)
nfsm_wcc_data(dvp, wccflag);
nfsmout:
VTONFS(dvp)->n_flag |= NMODIFIED;
nmp->n_flag |= NMODIFIED;
if (!wccflag)
NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
@ -848,12 +837,13 @@ nfsmout:
int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
//struct nfsnode *np = VTONFS(vp);
int tresid, error = 0;
int error = 0;
unsigned long *cookies = NULL;
int ncookies = 0, cnt;
int cnt;
struct nfsmount *nmp;
struct nfsnode *np;
int eof = 0;
uint64_t newoff;
//struct nfs_dirent *ndp;
fvdbg("Entry\n");
@ -864,6 +854,7 @@ int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
/* Recover our private data from the inode instance */
nmp = mountpt->i_private;
np = np->nm_head;
/* Make sure that the mount is still healthy */
@ -875,19 +866,22 @@ int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
goto errout_with_semaphore;
}
if (nmp->nfsv3_type != NFDIR)
return (EPERM);
if (np->nfsv3_type != NFDIR)
{
error = EPERM;
goto errout_with_semaphore;
}
#ifdef 0
/* First, check for hit on the EOF offset cache */
dir->u.nfs.nd_direoffset = np->nd_direoffset;
if (np->n_direofoffset != 0)
/* First, check for hit on the EOF offset */
if (dir->u.nfs.nd_direoffset != 0)
{
nfsstats.direofcache_hits++;
filep->f_oflags = 1;
//np->n_open = true;
return (0);
}
#endif
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
{
@ -897,49 +891,22 @@ int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
do
{
struct nfs_dirent *ndp = data;
dir->nfs->cookie[0] = ndp->cookie[0];
dir->nfs->cookie[1] = ndp->cookie[1];
dir->fd_dir = ndp->dirent;
error = nfs_readdirrpc(vp, &eof);
error = nfs_readdirrpc(nmp, &eof, dir);
if (error == NFSERR_BAD_COOKIE)
error = EINVAL;
while (error == 0 &&(ncookies != 0))
{
struct dirent *dp = &dir->fd_dir;
int reclen = dp->d_reclen;
dp->d_reclen -= NFS_DIRENT_OVERHEAD;
newoff = fxdr_hyper(&dir->nfs->cookie[0]);
*cookies = newoff;
cookies++;
ncookies--;
ndp = (struct nfs_dirent *)((uint8_t *) ndp + reclen);
dir->nfs->cookie[0] = ndp->cookie[0];
dir->nfs->cookie[1] = ndp->cookie[1];
dir->fd_dir = ndp->dirent;
}
}
while (!error && !eof && cnt--);
data = NULL;
if (!error && eof)
{
nfsstats.direofcache_misses++;
filep->f_oflags = 1;
nfs_semgive(nmp);
return (0);
}
filep->f_oflags = 0;
errout_with_semaphore:
nfs_semgive(nmp);
return (error);
}
@ -948,24 +915,23 @@ int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
/* Readdir rpc call. */
int nfs_readdirrpc(struct vnode *vp, int *end_of_directory)
int nfs_readdirrpc(struct nfsmount *nmp, int *end_of_directory, fs_dirent_s *dir)
{
int len, left;
struct nfs_dirent *ndp = NULL;
struct dirent *dp = NULL;
struct nfs_dirent *dp = NULL;
//struct nfsm_info info;
//u_int32_t *tl;
//uint32_t *tl;
/*caddr_t cp;
int32_t t1;
caddr_t cp2;*/
nfsuint64 cookie;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
struct nfsnode *dnp = VTONFS(vp);
uint64_t fileno;
int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
struct nfsnode *dnp = nmp->nm_head;
int error = 0, more_dirs = 1, blksiz = 0, bigenough = 1;
int attrflag;
int info_v3;
void *datareply;
info.nmi_v3 = NFS_ISV3(vp);
info_v3 = (nmp->nm_flag & NFSMNT_NFSV3);
/* Loop around doing readdir rpc's of size nm_readdirsize
* truncated to a multiple of NFS_READDIRBLKSIZ.
@ -975,130 +941,57 @@ int nfs_readdirrpc(struct vnode *vp, int *end_of_directory)
while (more_dirs && bigenough)
{
nfsstats.rpccnt[NFSPROC_READDIR]++;
if (info.nmi_v3) {
if (info_v3)
{
tl = nfsm_build(&info.nmi_mb, 5 * NFSX_UNSIGNED);
*tl++ = cookie.nfsuquad[0];
*tl++ = cookie.nfsuquad[1];
if (cookie.nfsuquad[0] == 0 && cookie.nfsuquad[1] == 0)
{
*tl++ = 0;
*tl++ = 0;
cookie.nfsuquad[0] = dnp->n_cookieverf.nfsuquad[0];
cookie.nfsuquad[1] = dnp->n_cookieverf.nfsuquad[1];
}
else
{
*tl++ = dnp->n_cookieverf.nfsuquad[0];
*tl++ = dnp->n_cookieverf.nfsuquad[1];
cookie.nfsuquad[1] = dnp->n_cookieverf.nfsuquad[1];
}
}
else
{
tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
*tl++ = cookie.nfsuquad[1];
}
*tl = txdr_unsigned(nmp->nm_readdirsize);
error = nfs_request(nmp, NFSPROC_READDIR, &info);
if (info.nmi_v3)
nfsm_postop_attr(vp, attrflag);
error = nfs_request(nmp, NFSPROC_READDIR, datareply);
dp = (void nfs_dirent*) datareply;
if (error)
{
goto nfsmout;
}
if (info.nmi_v3)
if (info_v3)
{
nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
dnp->n_cookieverf.nfsuquad[0] = *tl++;
dnp->n_cookieverf.nfsuquad[1] = *tl;
dnp->n_cookieverf.nfsuquad[0] = dp->cookie[0];
dnp->n_cookieverf.nfsuquad[1] = dp->cookie[1];
}
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
more_dirs = fxdr_unsigned(int, *tl);
more_dirs = fxdr_unsigned(int, *dp);
/* loop thru the dir entries, doctoring them to 4bsd form */
while (more_dirs && bigenough)
{
if (info.nmi_v3)
{
nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
fileno = fxdr_hyper(tl);
len = fxdr_unsigned(int, *(tl + 2));
}
else
{
nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
fileno = fxdr_unsigned(u_quad_t, *tl++);
len = fxdr_unsigned(int, *tl);
}
if (len <= 0 || len > NFS_MAXNAMLEN)
{
error = EBADRPC;
m_freem(info.nmi_mrep);
goto nfsmout;
}
tlen = nfsm_rndup(len + 1);
left = NFS_READDIRBLKSIZ - blksiz;
if ((tlen + NFS_DIRHDSIZ) > left)
{
dp->d_reclen += left;
uiop->uio_iov->iov_base += left;
uiop->uio_iov->iov_len -= left;
uiop->uio_resid -= left;
blksiz = 0;
}
if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
bigenough = 0;
if (bigenough)
{
ndp = (struct nfs_dirent *)uiop->uio_iov->iov_base;
dp = &ndp->dirent;
dp->d_fileno = (int)fileno;
dp->d_namlen = len;
dp->d_reclen = tlen + NFS_DIRHDSIZ;
dp->d_type = DT_UNKNOWN;
blksiz += dp->d_reclen;
if (blksiz == NFS_READDIRBLKSIZ)
blksiz = 0;
uiop->uio_resid -= NFS_DIRHDSIZ;
uiop->uio_iov->iov_base =
(char *)uiop->uio_iov->iov_base + NFS_DIRHDSIZ;
uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
nfsm_mtouio(uiop, len);
cp = uiop->uio_iov->iov_base;
tlen -= len;
*cp = '\0'; /* null terminate */
uiop->uio_iov->iov_base += tlen;
uiop->uio_iov->iov_len -= tlen;
uiop->uio_resid -= tlen;
}
else
nfsm_adv(nfsm_rndup(len));
if (info.nmi_v3)
if (info_v3)
{
nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
dir->u.nfs.cookie[0] = cookie.nfsuquad[0] = *tl++;
}
else
{
nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
dir->u.nfs.cookie[0] = ndp->cookie[0] = 0;
}
if (bigenough)
{
if (info.nmi_v3)
{
ndp->cookie[0] = cookie.nfsuquad[0] = *tl++;
}
else
ndp->cookie[0] = 0;
ndp->cookie[1] = cookie.nfsuquad[1] = *tl++;
dir->u.nfs.cookie[1] = ndp->cookie[1] = cookie.nfsuquad[1] = *tl++;
}
else if (info.nmi_v3)
else if (info_v3)
{
tl += 2;
}
else
{
tl++;
}
more_dirs = fxdr_unsigned(int, *tl);
}
@ -1111,16 +1004,6 @@ int nfs_readdirrpc(struct vnode *vp, int *end_of_directory)
}
}
/* Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
* by increasing d_reclen for the last record.
*/
if (blksiz > 0)
{
left = NFS_READDIRBLKSIZ - blksiz;
dp->d_reclen += left;
}
/* We are now either at the end of the directory or have filled the
* block.
*/
@ -1129,9 +1012,18 @@ int nfs_readdirrpc(struct vnode *vp, int *end_of_directory)
{
dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
if (end_of_directory)
{
*end_of_directory = 1;
}
/* We signal the end of the directory by returning the
* special error -ENOENT
*/
fdbg("End of directory\n");
error = ENOENT;
}
nfsmout:
return (error);
}
@ -1217,14 +1109,13 @@ errout_with_semaphore:
/* Print out the contents of an nfsnode. */
int nfs_print(void *v)
int nfs_print(struct file *filep)
{
struct vop_print_args *ap = v;
struct vnode *vp = ap->a_vp;
struct nfsnode *np = VTONFS(vp);
printf("tag VT_NFS, fileid %ld fsid 0x%lx",
np->n_vattr.va_fileid, np->n_vattr.va_fsid);
np->n_fattr.nfsv3fa_fileid, np->n_fattr.nfsv3fa_fsid);
printf("\n");
return (0);
}

View File

@ -118,8 +118,9 @@ struct fs_nxffsdir_s
#endif
#ifdef CONFIG_NFS
struct fs_nfsdir_s
struct nfsdir_s
{
off_t nd_direoffset; /* Directory EOF offset */
uint32_t cookie[2];
}
#endif
@ -175,7 +176,7 @@ struct fs_dirent_s
struct fs_nxffsdir_s nxffs;
#endif
#ifdef CONFIG_NFS
struct fs_nfsdir_s nfs;
struct nfsdir_s nfs;
#endif
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
} u;