summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2004-07-09 11:43:37 +0000
committerdes <des@FreeBSD.org>2004-07-09 11:43:37 +0000
commit881a348b52920d03375eddba5597f39a7262bd00 (patch)
treecf65be9a342015efbc1b8b209d33ac9430b202e9 /sys/fs
parentaf4e696e953ece3f0cf7c417ca94d4beea014cf7 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c18
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);
}
/*
OpenPOWER on IntegriCloud