diff options
author | des <des@FreeBSD.org> | 2004-07-09 11:43:37 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2004-07-09 11:43:37 +0000 |
commit | 881a348b52920d03375eddba5597f39a7262bd00 (patch) | |
tree | cf65be9a342015efbc1b8b209d33ac9430b202e9 | |
parent | af4e696e953ece3f0cf7c417ca94d4beea014cf7 (diff) | |
download | FreeBSD-src-881a348b52920d03375eddba5597f39a7262bd00.zip FreeBSD-src-881a348b52920d03375eddba5597f39a7262bd00.tar.gz |
Accumulate directory entries in a fixed-length sbuf, and uiomove them in
one go before returning. This avoids calling uiomove() while holding
allproc_lock.
Don't adjust uio->uio_offset manually, uiomove() does that for us.
Don't drop allproc_lock before calling panic().
Suggested by: alfred
-rw-r--r-- | sys/fs/pseudofs/pseudofs_vnops.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c index d21145b..d8fa427 100644 --- a/sys/fs/pseudofs/pseudofs_vnops.c +++ b/sys/fs/pseudofs/pseudofs_vnops.c @@ -606,6 +606,7 @@ pfs_readdir(struct vop_readdir_args *va) struct proc *p; off_t offset; int error, i, resid; + struct sbuf sb; PFS_TRACE((pd->pn_name)); @@ -623,12 +624,16 @@ pfs_readdir(struct vop_readdir_args *va) if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN) PFS_RETURN (EINVAL); + if (sbuf_new(&sb, NULL, resid, SBUF_FIXEDLEN) == NULL) + PFS_RETURN (ENOMEM); + /* skip unwanted entries */ sx_slock(&allproc_lock); for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) if (pfs_iterate(curthread, pid, pd, &pn, &p) == -1) { /* nothing left... */ sx_sunlock(&allproc_lock); + sbuf_delete(&sb); PFS_RETURN (0); } @@ -669,21 +674,18 @@ pfs_readdir(struct vop_readdir_args *va) entry.d_type = DT_LNK; break; default: - sx_sunlock(&allproc_lock); panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type); } PFS_TRACE((entry.d_name)); - if ((error = uiomove(&entry, PFS_DELEN, uio))) { - sx_sunlock(&allproc_lock); - PFS_RETURN (error); - } + sbuf_bcat(&sb, &entry, PFS_DELEN); offset += PFS_DELEN; resid -= PFS_DELEN; } - sx_sunlock(&allproc_lock); - uio->uio_offset += offset; - PFS_RETURN (0); + sbuf_finish(&sb); + error = uiomove(sbuf_data(&sb), sbuf_len(&sb), uio); + sbuf_delete(&sb); + PFS_RETURN (error); } /* |