Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs Tidy up ufs_readdir. First step only; there's plenty...
details: https://anonhg.NetBSD.org/src/rev/0df20a3d3e6d
branches: trunk
changeset: 825932:0df20a3d3e6d
user: dholland <dholland%NetBSD.org@localhost>
date: Mon Aug 07 06:53:48 2017 +0000
description:
Tidy up ufs_readdir. First step only; there's plenty more that could be
done to improve this code.
diffstat:
sys/ufs/lfs/ulfs_vnops.c | 212 +++++++++++++++++++++++++++-----------------
sys/ufs/ufs/ufs_vnops.c | 221 ++++++++++++++++++++++++++++------------------
2 files changed, 262 insertions(+), 171 deletions(-)
diffs (truncated from 561 to 300 lines):
diff -r f624bcbf8db9 -r 0df20a3d3e6d sys/ufs/lfs/ulfs_vnops.c
--- a/sys/ufs/lfs/ulfs_vnops.c Mon Aug 07 06:51:13 2017 +0000
+++ b/sys/ufs/lfs/ulfs_vnops.c Mon Aug 07 06:53:48 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ulfs_vnops.c,v 1.50 2017/08/04 07:27:42 maya Exp $ */
+/* $NetBSD: ulfs_vnops.c,v 1.51 2017/08/07 06:53:49 dholland Exp $ */
/* from NetBSD: ufs_vnops.c,v 1.232 2016/05/19 18:32:03 riastradh Exp */
/*-
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.50 2017/08/04 07:27:42 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.51 2017/08/07 06:53:49 dholland Exp $");
#if defined(_KERNEL_OPT)
#include "opt_lfs.h"
@@ -769,129 +769,173 @@
kauth_cred_t a_cred;
int *a_eofflag;
off_t **a_cookies;
- int *ncookies;
+ int *a_ncookies;
} */ *ap = v;
+
+ /* vnode and fs */
struct vnode *vp = ap->a_vp;
- LFS_DIRHEADER *cdp, *ecdp;
- struct dirent *ndp;
- char *cdbuf, *ndbuf, *endp;
- struct uio auio, *uio;
- struct iovec aiov;
- int error;
- size_t count, ccount, rcount, cdbufsz, ndbufsz;
- off_t off, *ccp;
- off_t startoff;
- size_t skipbytes;
struct ulfsmount *ump = VFSTOULFS(vp->v_mount);
struct lfs *fs = ump->um_lfs;
+ /* caller's buffer */
+ struct uio *calleruio = ap->a_uio;
+ off_t startoffset, endoffset;
+ size_t callerbytes;
+ off_t curoffset;
+ /* dirent production buffer */
+ char *direntbuf;
+ size_t direntbufmax;
+ struct dirent *dirent, *stopdirent;
+ /* output cookies array */
+ off_t *cookies;
+ size_t numcookies, maxcookies;
+ /* disk buffer */
+ off_t physstart, physend;
+ size_t skipstart, dropend;
+ char *rawbuf;
+ size_t rawbufmax, rawbytes;
+ struct uio rawuio;
+ struct iovec rawiov;
+ LFS_DIRHEADER *rawdp, *stoprawdp;
+ /* general */
+ int error;
KASSERT(VOP_ISLOCKED(vp));
- uio = ap->a_uio;
- count = uio->uio_resid;
- rcount = count - ((uio->uio_offset + count) & (fs->um_dirblksiz - 1));
+ /* figure out where we want to read */
+ callerbytes = calleruio->uio_resid;
+ startoffset = calleruio->uio_offset;
+ endoffset = startoffset + callerbytes;
- if (rcount < LFS_DIRECTSIZ(fs, 0) || count < _DIRENT_MINSIZE(ndp))
+ if (callerbytes < _DIRENT_MINSIZE(dirent)) {
+ /* no room for even one struct dirent */
return EINVAL;
+ }
- startoff = uio->uio_offset & ~(fs->um_dirblksiz - 1);
- skipbytes = uio->uio_offset - startoff;
- rcount += skipbytes;
+ /* round start and end down to block boundaries */
+ physstart = startoffset & ~(off_t)(fs->um_dirblksiz - 1);
+ physend = endoffset & ~(off_t)(fs->um_dirblksiz - 1);
+ skipstart = startoffset - physstart;
+ dropend = endoffset - physend;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = startoff;
- auio.uio_resid = rcount;
- UIO_SETUP_SYSSPACE(&auio);
- auio.uio_rw = UIO_READ;
- cdbufsz = rcount;
- cdbuf = kmem_alloc(cdbufsz, KM_SLEEP);
- aiov.iov_base = cdbuf;
- aiov.iov_len = rcount;
- error = VOP_READ(vp, &auio, 0, ap->a_cred);
+ if (callerbytes - dropend < LFS_DIRECTSIZ(fs, 0)) {
+ /* no room for even one dirheader + name */
+ return EINVAL;
+ }
+
+ /* how much to actually read */
+ rawbufmax = callerbytes + skipstart - dropend;
+
+ /* read it */
+ rawbuf = kmem_alloc(rawbufmax, KM_SLEEP);
+ rawiov.iov_base = rawbuf;
+ rawiov.iov_len = rawbufmax;
+ rawuio.uio_iov = &rawiov;
+ rawuio.uio_iovcnt = 1;
+ rawuio.uio_offset = physstart;
+ rawuio.uio_resid = rawbufmax;
+ UIO_SETUP_SYSSPACE(&rawuio);
+ rawuio.uio_rw = UIO_READ;
+ error = VOP_READ(vp, &rawuio, 0, ap->a_cred);
if (error != 0) {
- kmem_free(cdbuf, cdbufsz);
+ kmem_free(rawbuf, rawbufmax);
return error;
}
-
- rcount -= auio.uio_resid;
+ rawbytes = rawbufmax - rawuio.uio_resid;
- cdp = (LFS_DIRHEADER *)(void *)cdbuf;
- ecdp = (LFS_DIRHEADER *)(void *)&cdbuf[rcount];
+ /* the raw entries to iterate over */
+ rawdp = (LFS_DIRHEADER *)(void *)rawbuf;
+ stoprawdp = (LFS_DIRHEADER *)(void *)&rawbuf[rawbytes];
+
+ /* allocate space to produce dirents into */
+ direntbufmax = callerbytes;
+ direntbuf = kmem_alloc(direntbufmax, KM_SLEEP);
- ndbufsz = count;
- ndbuf = kmem_alloc(ndbufsz, KM_SLEEP);
- ndp = (struct dirent *)(void *)ndbuf;
- endp = &ndbuf[count];
+ /* the dirents to iterate over */
+ dirent = (struct dirent *)(void *)direntbuf;
+ stopdirent = (struct dirent *)(void *)&direntbuf[direntbufmax];
- off = uio->uio_offset;
+ /* the output "cookies" (seek positions of directory entries) */
if (ap->a_cookies) {
- ccount = rcount / LFS_DIRECTSIZ(fs, 1);
- ccp = *(ap->a_cookies) = malloc(ccount * sizeof(*ccp),
+ numcookies = 0;
+ maxcookies = rawbytes / LFS_DIRECTSIZ(fs, 1);
+ cookies = malloc(maxcookies * sizeof(*cookies),
M_TEMP, M_WAITOK);
} else {
/* XXX: GCC */
- ccount = 0;
- ccp = NULL;
+ maxcookies = 0;
+ cookies = NULL;
}
- while (cdp < ecdp) {
- if (skipbytes > 0) {
- if (lfs_dir_getreclen(fs, cdp) <= skipbytes) {
- skipbytes -= lfs_dir_getreclen(fs, cdp);
- cdp = LFS_NEXTDIR(fs, cdp);
+ /* now produce the dirents */
+ curoffset = calleruio->uio_offset;
+ while (rawdp < stoprawdp) {
+ if (skipstart > 0) {
+ /* drain skipstart */
+ if (lfs_dir_getreclen(fs, rawdp) <= skipstart) {
+ skipstart -= lfs_dir_getreclen(fs, rawdp);
+ rawdp = LFS_NEXTDIR(fs, rawdp);
continue;
}
- /*
- * invalid cookie.
- */
+ /* caller's start position wasn't on an entry */
error = EINVAL;
goto out;
}
- if (lfs_dir_getreclen(fs, cdp) == 0) {
- struct dirent *ondp = ndp;
- ndp->d_reclen = _DIRENT_MINSIZE(ndp);
- ndp = _DIRENT_NEXT(ndp);
- ondp->d_reclen = 0;
- cdp = ecdp;
+ if (lfs_dir_getreclen(fs, rawdp) == 0) {
+ struct dirent *save = dirent;
+ dirent->d_reclen = _DIRENT_MINSIZE(dirent);
+ dirent = _DIRENT_NEXT(dirent);
+ save->d_reclen = 0;
+ rawdp = stoprawdp;
break;
}
- ndp->d_type = lfs_dir_gettype(fs, cdp);
- ndp->d_namlen = lfs_dir_getnamlen(fs, cdp);
- ndp->d_reclen = _DIRENT_RECLEN(ndp, ndp->d_namlen);
- if ((char *)(void *)ndp + ndp->d_reclen +
- _DIRENT_MINSIZE(ndp) > endp)
+
+ /* copy the header */
+ dirent->d_type = lfs_dir_gettype(fs, rawdp);
+ dirent->d_namlen = lfs_dir_getnamlen(fs, rawdp);
+ dirent->d_reclen = _DIRENT_RECLEN(dirent, dirent->d_namlen);
+
+ /* stop if there isn't room for the name AND another header */
+ if ((char *)(void *)dirent + dirent->d_reclen +
+ _DIRENT_MINSIZE(dirent) > (char *)(void *)stopdirent)
break;
- ndp->d_fileno = lfs_dir_getino(fs, cdp);
- (void)memcpy(ndp->d_name, lfs_dir_nameptr(fs, cdp),
- ndp->d_namlen);
- memset(&ndp->d_name[ndp->d_namlen], 0,
- ndp->d_reclen - _DIRENT_NAMEOFF(ndp) - ndp->d_namlen);
- off += lfs_dir_getreclen(fs, cdp);
+
+ /* copy the name (and inode (XXX: why after the test?)) */
+ dirent->d_fileno = lfs_dir_getino(fs, rawdp);
+ (void)memcpy(dirent->d_name, lfs_dir_nameptr(fs, rawdp),
+ dirent->d_namlen);
+ memset(&dirent->d_name[dirent->d_namlen], 0,
+ dirent->d_reclen - _DIRENT_NAMEOFF(dirent)
+ - dirent->d_namlen);
+
+ /* onward */
+ curoffset += lfs_dir_getreclen(fs, rawdp);
if (ap->a_cookies) {
- KASSERT(ccp - *(ap->a_cookies) < ccount);
- *(ccp++) = off;
+ KASSERT(numcookies < maxcookies);
+ cookies[numcookies++] = curoffset;
}
- ndp = _DIRENT_NEXT(ndp);
- cdp = LFS_NEXTDIR(fs, cdp);
+ dirent = _DIRENT_NEXT(dirent);
+ rawdp = LFS_NEXTDIR(fs, rawdp);
}
- count = ((char *)(void *)ndp - ndbuf);
- error = uiomove(ndbuf, count, uio);
+ /* transfer the dirents to the caller's buffer */
+ callerbytes = ((char *)(void *)dirent - direntbuf);
+ error = uiomove(direntbuf, callerbytes, calleruio);
+
out:
+ calleruio->uio_offset = curoffset;
if (ap->a_cookies) {
if (error) {
- free(*(ap->a_cookies), M_TEMP);
- *(ap->a_cookies) = NULL;
- *(ap->a_ncookies) = 0;
+ free(cookies, M_TEMP);
+ *ap->a_cookies = NULL;
+ *ap->a_ncookies = 0;
} else {
- *ap->a_ncookies = ccp - *(ap->a_cookies);
+ *ap->a_cookies = cookies;
+ *ap->a_ncookies = numcookies;
}
}
- uio->uio_offset = off;
- kmem_free(ndbuf, ndbufsz);
- kmem_free(cdbuf, cdbufsz);
- *ap->a_eofflag = VTOI(vp)->i_size <= uio->uio_offset;
+ kmem_free(direntbuf, direntbufmax);
+ kmem_free(rawbuf, rawbufmax);
+ *ap->a_eofflag = VTOI(vp)->i_size <= calleruio->uio_offset;
return error;
}
diff -r f624bcbf8db9 -r 0df20a3d3e6d sys/ufs/ufs/ufs_vnops.c
--- a/sys/ufs/ufs/ufs_vnops.c Mon Aug 07 06:51:13 2017 +0000
+++ b/sys/ufs/ufs/ufs_vnops.c Mon Aug 07 06:53:48 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_vnops.c,v 1.237 2017/04/26 03:02:49 riastradh Exp $ */
+/* $NetBSD: ufs_vnops.c,v 1.238 2017/08/07 06:53:48 dholland Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.237 2017/04/26 03:02:49 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.238 2017/08/07 06:53:48 dholland Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -1219,19 +1219,11 @@
kauth_cred_t a_cred;
int *a_eofflag;
off_t **a_cookies;
- int *ncookies;
+ int *a_ncookies;
} */ *ap = v;
+
Home |
Main Index |
Thread Index |
Old Index