git: e9b713513a78 - main - pseudofs: Simplify pfs_readdir() and set eofflag

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Wed, 23 Jul 2025 16:22:59 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=e9b713513a78ccb01dbfa1a3f087f94b33531787

commit e9b713513a78ccb01dbfa1a3f087f94b33531787
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-07-23 01:52:38 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-07-23 16:20:31 +0000

    pseudofs: Simplify pfs_readdir() and set eofflag
    
    There were two loops, one to skip entries before the requested offset,
    and one to populate entries.  Merge them and use the return value of
    pfs_iterate() to decide whether to set eofflag.
    
    As a side effect, this fixes a small bug: the first loop would decrement
    `offset` to zero, and the second loop would increment it again.
    However, `offset` was used to set `d_off`, and we should include the
    starting offset there.
    
    Add a comment explaining the use of the allproc lock.
    
    Reviewed by:    des, kib
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D51462
---
 sys/fs/pseudofs/pseudofs_vnops.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index 0bdfedffafcb..8cd092118d0e 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -850,7 +850,7 @@ pfs_readdir(struct vop_readdir_args *va)
 	struct uio *uio;
 	struct pfsentry *pfsent, *pfsent2;
 	struct pfsdirentlist lst;
-	off_t offset;
+	off_t coffset, offset;
 	int error, i, resid;
 
 	STAILQ_INIT(&lst);
@@ -860,6 +860,9 @@ pfs_readdir(struct vop_readdir_args *va)
 	PFS_TRACE(("%s pid %lu", pd->pn_name, (unsigned long)pid));
 	pfs_assert_not_owned(pd);
 
+	if (va->a_eofflag != NULL)
+		*va->a_eofflag = 0;
+
 	if (vn->v_type != VDIR)
 		PFS_RETURN (ENOTDIR);
 	KASSERT_PN_IS_DIR(pd);
@@ -878,6 +881,10 @@ pfs_readdir(struct vop_readdir_args *va)
 	if (pid != NO_PID && !pfs_lookup_proc(pid, &proc))
 		PFS_RETURN (ENOENT);
 
+	/*
+	 * The allproc lock is required in pfs_iterate() for procdir
+	 * directories.
+	 */
 	sx_slock(&allproc_lock);
 	pfs_lock(pd);
 
@@ -897,23 +904,15 @@ pfs_readdir(struct vop_readdir_args *va)
 		}
 	}
 
-	/* skip unwanted entries */
-	for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) {
+	for (pn = NULL, p = NULL, coffset = 0; resid >= PFS_DELEN;
+	    coffset += PFS_DELEN) {
 		if (pfs_iterate(curthread, proc, pd, &pn, &p) == -1) {
-			/* nothing left... */
-			if (proc != NULL) {
-				_PRELE(proc);
-				PROC_UNLOCK(proc);
-			}
-			pfs_unlock(pd);
-			sx_sunlock(&allproc_lock);
-			PFS_RETURN (0);
+			if (va->a_eofflag != NULL)
+				*va->a_eofflag = 1;
+			break;
 		}
-	}
-
-	/* fill in entries */
-	while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 &&
-	    resid >= PFS_DELEN) {
+		if (coffset < offset)
+			continue;
 		if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV,
 		    M_NOWAIT | M_ZERO)) == NULL) {
 			error = ENOMEM;