summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1994-09-28 16:45:22 +0000
committerdfr <dfr@FreeBSD.org>1994-09-28 16:45:22 +0000
commit57b6c0c34c7d3130b7c00e4293686bd588419fe6 (patch)
tree31a9fd0d25f683274b252c0f76348271e04406c4 /sys
parentc49750310fc7779d5e19ee11d35ae43d4a9d4548 (diff)
downloadFreeBSD-src-57b6c0c34c7d3130b7c00e4293686bd588419fe6.zip
FreeBSD-src-57b6c0c34c7d3130b7c00e4293686bd588419fe6.tar.gz
Make NFS ask the filesystems for directory cookies instead of making them
itself.
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c39
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c74
-rw-r--r--sys/isofs/cd9660/cd9660_vnops.c39
-rw-r--r--sys/kern/vfs_extattr.c8
-rw-r--r--sys/kern/vfs_syscalls.c8
-rw-r--r--sys/kern/vnode_if.src5
-rw-r--r--sys/msdosfs/msdosfs_vnops.c74
-rw-r--r--sys/nfs/nfs_serv.c104
-rw-r--r--sys/nfsserver/nfs_serv.c104
-rw-r--r--sys/ufs/ufs/ufs_vnops.c42
10 files changed, 313 insertions, 184 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index eaac2a8..280f5f5 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vnops.c 8.3 (Berkeley) 1/23/94
- * $Id: cd9660_vnops.c,v 1.8 1994/09/22 19:37:46 wollman Exp $
+ * $Id: cd9660_vnops.c,v 1.9 1994/09/26 00:32:59 gpalmer Exp $
*/
#include <sys/param.h>
@@ -480,6 +480,8 @@ cd9660_readdir(ap)
struct iso_node *ip;
struct buf *bp = NULL;
u_short tmplen;
+ int ncookies = 0;
+ u_int *cookies = NULL;
ip = VTOI(ap->a_vp);
imp = ip->i_mnt;
@@ -488,13 +490,17 @@ cd9660_readdir(ap)
idp->saveent.d_namlen = 0;
idp->assocent.d_namlen = 0;
idp->uio = uio;
-#if 0
- idp->cookiep = cookies;
- idp->ncookies = ncookies;
- idp->eof = 1;
-#else
- idp->cookiep = 0;
-#endif
+ if (ap->a_ncookies != NULL) {
+ /*
+ * Guess the number of cookies needed.
+ */
+ ncookies = uio->uio_resid / 16;
+ MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
+ idp->cookiep = cookies;
+ idp->ncookies = ncookies;
+ } else
+ idp->cookiep = 0;
+ idp->eof = 0;
idp->curroff = uio->uio_offset;
entryoffsetinblock = iso_blkoff(imp, idp->curroff);
@@ -610,14 +616,25 @@ cd9660_readdir(ap)
}
if (error < 0)
error = 0;
+
+ if (ap->a_ncookies != NULL) {
+ if (error)
+ FREE(cookies, M_TEMP);
+ else {
+ /*
+ * Work out the number of cookies actually used.
+ */
+ *ap->a_ncookies = ncookies - idp->ncookies;
+ *ap->a_cookies = cookies;
+ }
+ }
if (bp)
brelse (bp);
uio->uio_offset = idp->uio_off;
-#if 0
- *eofflagp = idp->eof;
-#endif
+ if (ap->a_eofflag)
+ *ap->a_eofflag = idp->eof;
FREE(idp,M_TEMP);
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index 5235e2d..033c23a 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $Id: msdosfs_vnops.c,v 1.2 1994/09/21 03:47:17 wollman Exp $ */
+/* $Id: msdosfs_vnops.c,v 1.3 1994/09/27 20:42:56 phk Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */
/*-
@@ -1444,19 +1444,14 @@ msdosfs_readdir(ap)
struct dirent *crnt;
u_char dirbuf[512]; /* holds converted dos directories */
struct uio *uio = ap->a_uio;
- int ncookies = 1;
- u_int* cookies = NULL;
+ off_t off;
+ int ncookies = 0;
#ifdef MSDOSFS_DEBUG
printf("msdosfs_readdir(): vp %08x, uio %08x, cred %08x, eofflagp %08x\n",
ap->a_vp, uio, ap->a_cred, ap->a_eofflag);
#endif
-#if 0
- if (!ap->a_cookies)
- ncookies = 1;
-#endif
-
/*
* msdosfs_readdir() won't operate properly on regular files since
* it does i/o only with the the filesystem vnode, and hence can
@@ -1478,6 +1473,7 @@ msdosfs_readdir(ap)
return EINVAL;
uio->uio_resid = count;
uio->uio_iov->iov_len = count;
+ off = uio->uio_offset;
/*
* If they are reading from the root directory then, we simulate
@@ -1501,23 +1497,14 @@ msdosfs_readdir(ap)
n = 1;
if (!uio->uio_offset) {
n = 2;
- if (cookies) {
- *cookies++ = sizeof(struct direntry);
- ncookies--;
- }
+ ncookies++;
}
- if (cookies) {
- if (ncookies-- <= 0)
- n--;
- else
- *cookies++ = 2 * sizeof(struct direntry);
- }
-
+ ncookies++;
error = uiomove((char *) rootdots + uio->uio_offset,
n * sizeof(struct direntry), uio);
}
}
- while (!error && uio->uio_resid > 0 && ncookies > 0) {
+ while (!error && uio->uio_resid > 0) {
lbn = (uio->uio_offset - bias) >> pmp->pm_cnshift;
on = (uio->uio_offset - bias) & pmp->pm_crbomask;
n = min((u_long) (pmp->pm_bpcluster - on), uio->uio_resid);
@@ -1561,10 +1548,6 @@ msdosfs_readdir(ap)
(dentp->deAttributes & ATTR_VOLUME)) {
if (prev) {
prev->d_reclen += sizeof(struct direntry);
- if (cookies) {
- ncookies++;
- cookies--;
- }
} else {
prev = crnt;
prev->d_fileno = 0;
@@ -1572,6 +1555,7 @@ msdosfs_readdir(ap)
prev->d_type = DT_UNKNOWN;
prev->d_namlen = 0;
prev->d_name[0] = 0;
+ ncookies++;
}
} else {
/*
@@ -1606,13 +1590,9 @@ msdosfs_readdir(ap)
* dentp->deStartCluster);
*/
prev = crnt;
+ ncookies++;
}
dentp++;
- if (cookies) {
- *cookies++ = (u_int)((char *)dentp - bp->b_data - on)
- + uio->uio_offset;
- ncookies--;
- }
crnt = (struct dirent *) ((char *) crnt + sizeof(struct direntry));
pushout = 1;
@@ -1634,8 +1614,6 @@ msdosfs_readdir(ap)
prev = 0;
crnt = (struct dirent *) dirbuf;
}
- if (ncookies <= 0)
- break;
}
if (pushout) {
pushout = 0;
@@ -1659,18 +1637,40 @@ msdosfs_readdir(ap)
}
out: ;
uio->uio_resid += lost;
+ if (!error && ap->a_ncookies != NULL) {
+ struct dirent* dpStart;
+ struct dirent* dpEnd;
+ struct dirent* dp;
+ u_int *cookies;
+ u_int *cookiep;
+
+ if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
+ panic("msdosfs_readdir: unexpected uio from NFS server");
+ dpStart = (struct dirent *)
+ (uio->uio_iov->iov_base - (uio->uio_offset - off));
+ dpEnd = (struct dirent *) uio->uio_iov->iov_base;
+ MALLOC(cookies, u_int *, ncookies * sizeof(u_int),
+ M_TEMP, M_WAITOK);
+ for (dp = dpStart, cookiep = cookies;
+ dp < dpEnd;
+ dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
+ off += dp->d_reclen;
+ *cookiep++ = (u_int) off;
+ }
+ *ap->a_ncookies = ncookies;
+ *ap->a_cookies = cookies;
+ }
-#if 0
/*
* I don't know why we bother setting this eofflag, getdirentries()
* in vfs_syscalls.c doesn't bother to look at it when we return.
* (because NFS uses it in nfs_serv.c -- JMP)
*/
- if (dep->de_FileSize - uio->uio_offset - bias <= 0)
- *ap->a_eofflag = 1;
- else
- *ap->a_eofflag = 0;
-#endif
+ if (ap->a_eofflag)
+ if (dep->de_FileSize - uio->uio_offset - bias <= 0)
+ *ap->a_eofflag = 1;
+ else
+ *ap->a_eofflag = 0;
return error;
}
diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c
index eaac2a8..280f5f5 100644
--- a/sys/isofs/cd9660/cd9660_vnops.c
+++ b/sys/isofs/cd9660/cd9660_vnops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vnops.c 8.3 (Berkeley) 1/23/94
- * $Id: cd9660_vnops.c,v 1.8 1994/09/22 19:37:46 wollman Exp $
+ * $Id: cd9660_vnops.c,v 1.9 1994/09/26 00:32:59 gpalmer Exp $
*/
#include <sys/param.h>
@@ -480,6 +480,8 @@ cd9660_readdir(ap)
struct iso_node *ip;
struct buf *bp = NULL;
u_short tmplen;
+ int ncookies = 0;
+ u_int *cookies = NULL;
ip = VTOI(ap->a_vp);
imp = ip->i_mnt;
@@ -488,13 +490,17 @@ cd9660_readdir(ap)
idp->saveent.d_namlen = 0;
idp->assocent.d_namlen = 0;
idp->uio = uio;
-#if 0
- idp->cookiep = cookies;
- idp->ncookies = ncookies;
- idp->eof = 1;
-#else
- idp->cookiep = 0;
-#endif
+ if (ap->a_ncookies != NULL) {
+ /*
+ * Guess the number of cookies needed.
+ */
+ ncookies = uio->uio_resid / 16;
+ MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
+ idp->cookiep = cookies;
+ idp->ncookies = ncookies;
+ } else
+ idp->cookiep = 0;
+ idp->eof = 0;
idp->curroff = uio->uio_offset;
entryoffsetinblock = iso_blkoff(imp, idp->curroff);
@@ -610,14 +616,25 @@ cd9660_readdir(ap)
}
if (error < 0)
error = 0;
+
+ if (ap->a_ncookies != NULL) {
+ if (error)
+ FREE(cookies, M_TEMP);
+ else {
+ /*
+ * Work out the number of cookies actually used.
+ */
+ *ap->a_ncookies = ncookies - idp->ncookies;
+ *ap->a_cookies = cookies;
+ }
+ }
if (bp)
brelse (bp);
uio->uio_offset = idp->uio_off;
-#if 0
- *eofflagp = idp->eof;
-#endif
+ if (ap->a_eofflag)
+ *ap->a_eofflag = idp->eof;
FREE(idp,M_TEMP);
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 4607112..21fc5ee 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
- * $Id: vfs_syscalls.c,v 1.7 1994/09/21 03:46:49 wollman Exp $
+ * $Id: vfs_syscalls.c,v 1.8 1994/09/22 19:37:56 wollman Exp $
*/
#include <sys/param.h>
@@ -1970,7 +1970,7 @@ ogetdirentries(p, uap, retval)
loff = auio.uio_offset = fp->f_offset;
# if (BYTE_ORDER != LITTLE_ENDIAN)
if (vp->v_mount->mnt_maxsymlinklen <= 0) {
- error = VOP_READDIR(vp, &auio, fp->f_cred);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
fp->f_offset = auio.uio_offset;
} else
# endif
@@ -1981,7 +1981,7 @@ ogetdirentries(p, uap, retval)
kiov.iov_len = uap->count;
MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred);
+ error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL);
fp->f_offset = kuio.uio_offset;
if (error == 0) {
readcnt = uap->count - kuio.uio_resid;
@@ -2066,7 +2066,7 @@ unionread:
auio.uio_resid = uap->count;
VOP_LOCK(vp);
loff = auio.uio_offset = fp->f_offset;
- error = VOP_READDIR(vp, &auio, fp->f_cred);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
fp->f_offset = auio.uio_offset;
VOP_UNLOCK(vp);
if (error)
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 4607112..21fc5ee 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
- * $Id: vfs_syscalls.c,v 1.7 1994/09/21 03:46:49 wollman Exp $
+ * $Id: vfs_syscalls.c,v 1.8 1994/09/22 19:37:56 wollman Exp $
*/
#include <sys/param.h>
@@ -1970,7 +1970,7 @@ ogetdirentries(p, uap, retval)
loff = auio.uio_offset = fp->f_offset;
# if (BYTE_ORDER != LITTLE_ENDIAN)
if (vp->v_mount->mnt_maxsymlinklen <= 0) {
- error = VOP_READDIR(vp, &auio, fp->f_cred);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
fp->f_offset = auio.uio_offset;
} else
# endif
@@ -1981,7 +1981,7 @@ ogetdirentries(p, uap, retval)
kiov.iov_len = uap->count;
MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred);
+ error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL);
fp->f_offset = kuio.uio_offset;
if (error == 0) {
readcnt = uap->count - kuio.uio_resid;
@@ -2066,7 +2066,7 @@ unionread:
auio.uio_resid = uap->count;
VOP_LOCK(vp);
loff = auio.uio_offset = fp->f_offset;
- error = VOP_READDIR(vp, &auio, fp->f_cred);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
fp->f_offset = auio.uio_offset;
VOP_UNLOCK(vp);
if (error)
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index c2b012e..4e36675 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -31,7 +31,7 @@
# SUCH DAMAGE.
#
# @(#)vnode_if.src 8.3 (Berkeley) 2/3/94
-# $Id$
+# $Id: vnode_if.src,v 1.2 1994/08/02 07:43:37 davidg Exp $
#
vop_lookup {
IN struct vnode *dvp;
@@ -188,6 +188,9 @@ vop_readdir {
IN struct vnode *vp;
INOUT struct uio *uio;
IN struct ucred *cred;
+ INOUT int *eofflag;
+ INOUT int *ncookies;
+ INOUT u_int **cookies;
};
vop_readlink {
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index 5235e2d..033c23a 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $Id: msdosfs_vnops.c,v 1.2 1994/09/21 03:47:17 wollman Exp $ */
+/* $Id: msdosfs_vnops.c,v 1.3 1994/09/27 20:42:56 phk Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */
/*-
@@ -1444,19 +1444,14 @@ msdosfs_readdir(ap)
struct dirent *crnt;
u_char dirbuf[512]; /* holds converted dos directories */
struct uio *uio = ap->a_uio;
- int ncookies = 1;
- u_int* cookies = NULL;
+ off_t off;
+ int ncookies = 0;
#ifdef MSDOSFS_DEBUG
printf("msdosfs_readdir(): vp %08x, uio %08x, cred %08x, eofflagp %08x\n",
ap->a_vp, uio, ap->a_cred, ap->a_eofflag);
#endif
-#if 0
- if (!ap->a_cookies)
- ncookies = 1;
-#endif
-
/*
* msdosfs_readdir() won't operate properly on regular files since
* it does i/o only with the the filesystem vnode, and hence can
@@ -1478,6 +1473,7 @@ msdosfs_readdir(ap)
return EINVAL;
uio->uio_resid = count;
uio->uio_iov->iov_len = count;
+ off = uio->uio_offset;
/*
* If they are reading from the root directory then, we simulate
@@ -1501,23 +1497,14 @@ msdosfs_readdir(ap)
n = 1;
if (!uio->uio_offset) {
n = 2;
- if (cookies) {
- *cookies++ = sizeof(struct direntry);
- ncookies--;
- }
+ ncookies++;
}
- if (cookies) {
- if (ncookies-- <= 0)
- n--;
- else
- *cookies++ = 2 * sizeof(struct direntry);
- }
-
+ ncookies++;
error = uiomove((char *) rootdots + uio->uio_offset,
n * sizeof(struct direntry), uio);
}
}
- while (!error && uio->uio_resid > 0 && ncookies > 0) {
+ while (!error && uio->uio_resid > 0) {
lbn = (uio->uio_offset - bias) >> pmp->pm_cnshift;
on = (uio->uio_offset - bias) & pmp->pm_crbomask;
n = min((u_long) (pmp->pm_bpcluster - on), uio->uio_resid);
@@ -1561,10 +1548,6 @@ msdosfs_readdir(ap)
(dentp->deAttributes & ATTR_VOLUME)) {
if (prev) {
prev->d_reclen += sizeof(struct direntry);
- if (cookies) {
- ncookies++;
- cookies--;
- }
} else {
prev = crnt;
prev->d_fileno = 0;
@@ -1572,6 +1555,7 @@ msdosfs_readdir(ap)
prev->d_type = DT_UNKNOWN;
prev->d_namlen = 0;
prev->d_name[0] = 0;
+ ncookies++;
}
} else {
/*
@@ -1606,13 +1590,9 @@ msdosfs_readdir(ap)
* dentp->deStartCluster);
*/
prev = crnt;
+ ncookies++;
}
dentp++;
- if (cookies) {
- *cookies++ = (u_int)((char *)dentp - bp->b_data - on)
- + uio->uio_offset;
- ncookies--;
- }
crnt = (struct dirent *) ((char *) crnt + sizeof(struct direntry));
pushout = 1;
@@ -1634,8 +1614,6 @@ msdosfs_readdir(ap)
prev = 0;
crnt = (struct dirent *) dirbuf;
}
- if (ncookies <= 0)
- break;
}
if (pushout) {
pushout = 0;
@@ -1659,18 +1637,40 @@ msdosfs_readdir(ap)
}
out: ;
uio->uio_resid += lost;
+ if (!error && ap->a_ncookies != NULL) {
+ struct dirent* dpStart;
+ struct dirent* dpEnd;
+ struct dirent* dp;
+ u_int *cookies;
+ u_int *cookiep;
+
+ if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
+ panic("msdosfs_readdir: unexpected uio from NFS server");
+ dpStart = (struct dirent *)
+ (uio->uio_iov->iov_base - (uio->uio_offset - off));
+ dpEnd = (struct dirent *) uio->uio_iov->iov_base;
+ MALLOC(cookies, u_int *, ncookies * sizeof(u_int),
+ M_TEMP, M_WAITOK);
+ for (dp = dpStart, cookiep = cookies;
+ dp < dpEnd;
+ dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
+ off += dp->d_reclen;
+ *cookiep++ = (u_int) off;
+ }
+ *ap->a_ncookies = ncookies;
+ *ap->a_cookies = cookies;
+ }
-#if 0
/*
* I don't know why we bother setting this eofflag, getdirentries()
* in vfs_syscalls.c doesn't bother to look at it when we return.
* (because NFS uses it in nfs_serv.c -- JMP)
*/
- if (dep->de_FileSize - uio->uio_offset - bias <= 0)
- *ap->a_eofflag = 1;
- else
- *ap->a_eofflag = 0;
-#endif
+ if (ap->a_eofflag)
+ if (dep->de_FileSize - uio->uio_offset - bias <= 0)
+ *ap->a_eofflag = 1;
+ else
+ *ap->a_eofflag = 0;
return error;
}
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
index 55897c4..d43a86e 100644
--- a/sys/nfs/nfs_serv.c
+++ b/sys/nfs/nfs_serv.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
- * $Id: nfs_serv.c,v 1.4 1994/08/29 06:09:06 davidg Exp $
+ * $Id: nfs_serv.c,v 1.5 1994/09/22 19:38:25 wollman Exp $
*/
/*
@@ -1382,14 +1382,15 @@ nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
int len, nlen, rem, xfer, tsiz, i, error = 0;
int siz, cnt, fullsiz, eofflag, rdonly, cache;
u_quad_t frev;
- u_long on, off, toff;
+ u_long off, toff;
+ int ncookies;
+ u_int *cookies;
+ u_int *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
- toff = fxdr_unsigned(u_long, *tl++);
- off = (toff & ~(NFS_DIRBLKSIZ-1));
- on = (toff & (NFS_DIRBLKSIZ-1));
+ off = toff = fxdr_unsigned(u_long, *tl++);
cnt = fxdr_unsigned(int, *tl);
siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
if (cnt > NFS_MAXREADDIR)
@@ -1414,17 +1415,27 @@ again:
io.uio_segflg = UIO_SYSSPACE;
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
- error = VOP_READDIR(vp, &io, cred);
+ cookies = NULL;
+ eofflag = 0;
+ error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
off = (off_t)io.uio_offset;
if (error) {
vrele(vp);
free((caddr_t)rbuf, M_TEMP);
nfsm_reply(0);
}
- if (io.uio_resid < fullsiz)
- eofflag = 0;
- else
- eofflag = 1;
+ if (cookies == NULL) {
+ /*
+ * If the filesystem doen't support cookies, return eof.
+ */
+ vrele(vp);
+ nfsm_reply(2*NFSX_UNSIGNED);
+ nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+ *tl++ = nfs_false;
+ *tl = nfs_true;
+ FREE((caddr_t)rbuf, M_TEMP);
+ return (0);
+ }
if (io.uio_resid) {
siz -= io.uio_resid;
@@ -1439,6 +1450,7 @@ again:
*tl++ = nfs_false;
*tl = nfs_true;
FREE((caddr_t)rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
return (0);
}
}
@@ -1447,23 +1459,24 @@ again:
* Check for degenerate cases of nothing useful read.
* If so go try again
*/
- cpos = rbuf + on;
+ cpos = rbuf;
cend = rbuf + siz;
dp = (struct dirent *)cpos;
- while (cpos < cend && dp->d_fileno == 0) {
+ cookiep = cookies;
+ while (cpos < cend && ncookies > 0
+ && (*cookiep <= toff || dp->d_fileno == 0)) {
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
+ ncookies--;
}
if (cpos >= cend) {
toff = off;
siz = fullsiz;
- on = 0;
+ FREE(cookies, M_TEMP);
goto again;
}
- cpos = rbuf + on;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */
nfsm_reply(siz);
mp = mp2 = mb;
@@ -1515,13 +1528,12 @@ again:
nfsm_clget;
/* Finish off the record */
- toff += dp->d_reclen;
- *tl = txdr_unsigned(toff);
+ *tl = txdr_unsigned(*cookiep);
bp += NFSX_UNSIGNED;
- } else
- toff += dp->d_reclen;
+ }
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
}
vrele(vp);
nfsm_clget;
@@ -1539,6 +1551,7 @@ again:
} else
mp->m_len += bp - bpos;
FREE(rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
nfsm_srvdone;
}
@@ -1570,14 +1583,15 @@ nqnfsrv_readdirlook(nfsd, mrep, md, dpos, cred, nam, mrq)
int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;
int siz, cnt, fullsiz, eofflag, rdonly, cache;
u_quad_t frev, frev2;
- u_long on, off, toff;
+ u_long off, toff;
+ int ncookies;
+ u_int *cookies;
+ u_int *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
- toff = fxdr_unsigned(u_long, *tl++);
- off = (toff & ~(NFS_DIRBLKSIZ-1));
- on = (toff & (NFS_DIRBLKSIZ-1));
+ toff = off = fxdr_unsigned(u_long, *tl++);
cnt = fxdr_unsigned(int, *tl++);
duration2 = fxdr_unsigned(int, *tl);
siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
@@ -1603,17 +1617,27 @@ again:
io.uio_segflg = UIO_SYSSPACE;
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
- error = VOP_READDIR(vp, &io, cred);
+ cookies = NULL;
+ eofflag = 0;
+ error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
off = (u_long)io.uio_offset;
if (error) {
vrele(vp);
free((caddr_t)rbuf, M_TEMP);
nfsm_reply(0);
}
- if (io.uio_resid < fullsiz)
- eofflag = 0;
- else
- eofflag = 1;
+ if (cookies == NULL) {
+ /*
+ * If the filesystem doen't support cookies, return eof.
+ */
+ vrele(vp);
+ nfsm_reply(2*NFSX_UNSIGNED);
+ nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+ *tl++ = nfs_false;
+ *tl = nfs_true;
+ FREE((caddr_t)rbuf, M_TEMP);
+ return (0);
+ }
if (io.uio_resid) {
siz -= io.uio_resid;
@@ -1628,6 +1652,7 @@ again:
*tl++ = nfs_false;
*tl = nfs_true;
FREE((caddr_t)rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
return (0);
}
}
@@ -1636,23 +1661,24 @@ again:
* Check for degenerate cases of nothing useful read.
* If so go try again
*/
- cpos = rbuf + on;
+ cpos = rbuf;
cend = rbuf + siz;
dp = (struct dirent *)cpos;
- while (cpos < cend && dp->d_fileno == 0) {
+ cookiep = cookies;
+ while (cpos < cend && ncookies > 0
+ && (*cookiep <= toff || dp->d_fileno == 0)) {
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
+ ncookies--;
}
if (cpos >= cend) {
toff = off;
siz = fullsiz;
- on = 0;
+ FREE(cookies, M_TEMP);
goto again;
}
- cpos = rbuf + on;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
nfsm_reply(siz);
mp = mp2 = mb;
@@ -1752,14 +1778,13 @@ again:
nfsm_clget;
/* Finish off the record */
- toff += dp->d_reclen;
- *tl = txdr_unsigned(toff);
+ *tl = txdr_unsigned(*cookiep);
bp += NFSX_UNSIGNED;
- } else
+ }
invalid:
- toff += dp->d_reclen;
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
}
vrele(vp);
nfsm_clget;
@@ -1777,6 +1802,7 @@ invalid:
} else
mp->m_len += bp - bpos;
FREE(rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
nfsm_srvdone;
}
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 55897c4..d43a86e 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_serv.c 8.3 (Berkeley) 1/12/94
- * $Id: nfs_serv.c,v 1.4 1994/08/29 06:09:06 davidg Exp $
+ * $Id: nfs_serv.c,v 1.5 1994/09/22 19:38:25 wollman Exp $
*/
/*
@@ -1382,14 +1382,15 @@ nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
int len, nlen, rem, xfer, tsiz, i, error = 0;
int siz, cnt, fullsiz, eofflag, rdonly, cache;
u_quad_t frev;
- u_long on, off, toff;
+ u_long off, toff;
+ int ncookies;
+ u_int *cookies;
+ u_int *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
- toff = fxdr_unsigned(u_long, *tl++);
- off = (toff & ~(NFS_DIRBLKSIZ-1));
- on = (toff & (NFS_DIRBLKSIZ-1));
+ off = toff = fxdr_unsigned(u_long, *tl++);
cnt = fxdr_unsigned(int, *tl);
siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
if (cnt > NFS_MAXREADDIR)
@@ -1414,17 +1415,27 @@ again:
io.uio_segflg = UIO_SYSSPACE;
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
- error = VOP_READDIR(vp, &io, cred);
+ cookies = NULL;
+ eofflag = 0;
+ error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
off = (off_t)io.uio_offset;
if (error) {
vrele(vp);
free((caddr_t)rbuf, M_TEMP);
nfsm_reply(0);
}
- if (io.uio_resid < fullsiz)
- eofflag = 0;
- else
- eofflag = 1;
+ if (cookies == NULL) {
+ /*
+ * If the filesystem doen't support cookies, return eof.
+ */
+ vrele(vp);
+ nfsm_reply(2*NFSX_UNSIGNED);
+ nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+ *tl++ = nfs_false;
+ *tl = nfs_true;
+ FREE((caddr_t)rbuf, M_TEMP);
+ return (0);
+ }
if (io.uio_resid) {
siz -= io.uio_resid;
@@ -1439,6 +1450,7 @@ again:
*tl++ = nfs_false;
*tl = nfs_true;
FREE((caddr_t)rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
return (0);
}
}
@@ -1447,23 +1459,24 @@ again:
* Check for degenerate cases of nothing useful read.
* If so go try again
*/
- cpos = rbuf + on;
+ cpos = rbuf;
cend = rbuf + siz;
dp = (struct dirent *)cpos;
- while (cpos < cend && dp->d_fileno == 0) {
+ cookiep = cookies;
+ while (cpos < cend && ncookies > 0
+ && (*cookiep <= toff || dp->d_fileno == 0)) {
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
+ ncookies--;
}
if (cpos >= cend) {
toff = off;
siz = fullsiz;
- on = 0;
+ FREE(cookies, M_TEMP);
goto again;
}
- cpos = rbuf + on;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
len = 3*NFSX_UNSIGNED; /* paranoia, probably can be 0 */
nfsm_reply(siz);
mp = mp2 = mb;
@@ -1515,13 +1528,12 @@ again:
nfsm_clget;
/* Finish off the record */
- toff += dp->d_reclen;
- *tl = txdr_unsigned(toff);
+ *tl = txdr_unsigned(*cookiep);
bp += NFSX_UNSIGNED;
- } else
- toff += dp->d_reclen;
+ }
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
}
vrele(vp);
nfsm_clget;
@@ -1539,6 +1551,7 @@ again:
} else
mp->m_len += bp - bpos;
FREE(rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
nfsm_srvdone;
}
@@ -1570,14 +1583,15 @@ nqnfsrv_readdirlook(nfsd, mrep, md, dpos, cred, nam, mrq)
int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;
int siz, cnt, fullsiz, eofflag, rdonly, cache;
u_quad_t frev, frev2;
- u_long on, off, toff;
+ u_long off, toff;
+ int ncookies;
+ u_int *cookies;
+ u_int *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
- toff = fxdr_unsigned(u_long, *tl++);
- off = (toff & ~(NFS_DIRBLKSIZ-1));
- on = (toff & (NFS_DIRBLKSIZ-1));
+ toff = off = fxdr_unsigned(u_long, *tl++);
cnt = fxdr_unsigned(int, *tl++);
duration2 = fxdr_unsigned(int, *tl);
siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
@@ -1603,17 +1617,27 @@ again:
io.uio_segflg = UIO_SYSSPACE;
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
- error = VOP_READDIR(vp, &io, cred);
+ cookies = NULL;
+ eofflag = 0;
+ error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
off = (u_long)io.uio_offset;
if (error) {
vrele(vp);
free((caddr_t)rbuf, M_TEMP);
nfsm_reply(0);
}
- if (io.uio_resid < fullsiz)
- eofflag = 0;
- else
- eofflag = 1;
+ if (cookies == NULL) {
+ /*
+ * If the filesystem doen't support cookies, return eof.
+ */
+ vrele(vp);
+ nfsm_reply(2*NFSX_UNSIGNED);
+ nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+ *tl++ = nfs_false;
+ *tl = nfs_true;
+ FREE((caddr_t)rbuf, M_TEMP);
+ return (0);
+ }
if (io.uio_resid) {
siz -= io.uio_resid;
@@ -1628,6 +1652,7 @@ again:
*tl++ = nfs_false;
*tl = nfs_true;
FREE((caddr_t)rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
return (0);
}
}
@@ -1636,23 +1661,24 @@ again:
* Check for degenerate cases of nothing useful read.
* If so go try again
*/
- cpos = rbuf + on;
+ cpos = rbuf;
cend = rbuf + siz;
dp = (struct dirent *)cpos;
- while (cpos < cend && dp->d_fileno == 0) {
+ cookiep = cookies;
+ while (cpos < cend && ncookies > 0
+ && (*cookiep <= toff || dp->d_fileno == 0)) {
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
+ ncookies--;
}
if (cpos >= cend) {
toff = off;
siz = fullsiz;
- on = 0;
+ FREE(cookies, M_TEMP);
goto again;
}
- cpos = rbuf + on;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
nfsm_reply(siz);
mp = mp2 = mb;
@@ -1752,14 +1778,13 @@ again:
nfsm_clget;
/* Finish off the record */
- toff += dp->d_reclen;
- *tl = txdr_unsigned(toff);
+ *tl = txdr_unsigned(*cookiep);
bp += NFSX_UNSIGNED;
- } else
+ }
invalid:
- toff += dp->d_reclen;
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
+ cookiep++;
}
vrele(vp);
nfsm_clget;
@@ -1777,6 +1802,7 @@ invalid:
} else
mp->m_len += bp - bpos;
FREE(rbuf, M_TEMP);
+ FREE(cookies, M_TEMP);
nfsm_srvdone;
}
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index f7eeacf..ae8a14c 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94
- * $Id: ufs_vnops.c,v 1.5 1994/09/22 19:38:41 wollman Exp $
+ * $Id: ufs_vnops.c,v 1.6 1994/09/27 20:33:37 phk Exp $
*/
#include <sys/param.h>
@@ -1353,11 +1353,21 @@ ufs_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_ncookies;
+ u_int **cookies;
} */ *ap;
{
register struct uio *uio = ap->a_uio;
+ off_t off;
int count, lost, error;
+ if (ap->a_ncookies != NULL)
+ /*
+ * Ensure that the block is aligned. The caller can use
+ * the cookies to determine where in the block to start.
+ */
+ uio->uio_offset &= ~(DIRBLKSIZ - 1);
+ off = uio->uio_offset;
count = uio->uio_resid;
count &= ~(DIRBLKSIZ - 1);
lost = uio->uio_resid - count;
@@ -1407,6 +1417,36 @@ ufs_readdir(ap)
# else
error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
# endif
+ if (!error && ap->a_ncookies != NULL) {
+ struct dirent* dpStart;
+ struct dirent* dpEnd;
+ struct dirent* dp;
+ int ncookies;
+ u_int *cookies;
+ u_int *cookiep;
+
+ if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
+ panic("ufs_readdir: unexpected uio from NFS server");
+ dpStart = (struct dirent *)
+ (uio->uio_iov->iov_base - (uio->uio_offset - off));
+ dpEnd = (struct dirent *) uio->uio_iov->iov_base;
+ for (dp = dpStart, ncookies = 0;
+ dp < dpEnd;
+ dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
+ ncookies++;
+ MALLOC(cookies, u_int *, ncookies * sizeof(u_int),
+ M_TEMP, M_WAITOK);
+ for (dp = dpStart, cookiep = cookies;
+ dp < dpEnd;
+ dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
+ off += dp->d_reclen;
+ *cookiep++ = (u_int) off;
+ }
+ *ap->a_ncookies = ncookies;
+ *ap->a_cookies = cookies;
+ }
+ if (ap->a_eofflag)
+ *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
uio->uio_resid += lost;
return (error);
}
OpenPOWER on IntegriCloud