The branch main has been updated by markj:

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

commit e9b713513a78ccb01dbfa1a3f087f94b33531787
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2025-07-23 01:52:38 +0000
Commit:     Mark Johnston <ma...@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;

Reply via email to