git: 4b69f1fab66d - main - descriptors: add fget_remote_foreach()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 24 Mar 2025 02:24:45 UTC
The branch main has been updated by kib:

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

commit 4b69f1fab66db4fd3f874e78a457e317cd498d36
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-03-18 02:10:03 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-03-24 02:24:13 +0000

    descriptors: add fget_remote_foreach()
    
    Suggested by:   markj
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D49372
---
 sys/kern/kern_descrip.c | 41 +++++++++++++++++++++++++++++++++++++++++
 sys/sys/file.h          |  2 ++
 2 files changed, 43 insertions(+)

diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index dcb1f5d921db..9d81c30df328 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -2993,6 +2993,47 @@ fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp)
 	return (error);
 }
 
+int
+fget_remote_foreach(struct thread *td, struct proc *p,
+    int (*fn)(struct proc *, int, struct file *, void *), void *arg)
+{
+	struct filedesc *fdp;
+	struct fdescenttbl *fdt;
+	struct file *fp;
+	int error, error1, fd, highfd;
+
+	error = 0;
+	PROC_LOCK(p);
+	fdp = fdhold(p);
+	PROC_UNLOCK(p);
+	if (fdp == NULL)
+		return (ENOENT);
+
+	FILEDESC_SLOCK(fdp);
+	if (refcount_load(&fdp->fd_refcnt) != 0) {
+		fdt = atomic_load_ptr(&fdp->fd_files);
+		highfd = fdt->fdt_nfiles - 1;
+		FILEDESC_SUNLOCK(fdp);
+	} else {
+		error = ENOENT;
+		FILEDESC_SUNLOCK(fdp);
+		goto out;
+	}
+
+	for (fd = 0; fd <= highfd; fd++) {
+		error1 = fget_remote(td, p, fd, &fp);
+		if (error1 != 0)
+			continue;
+		error = fn(p, fd, fp, arg);
+		fdrop(fp, td);
+		if (error != 0)
+			break;
+	}
+out:
+	fddrop(fdp);
+	return (error);
+}
+
 #ifdef CAPABILITIES
 int
 fgetvp_lookup_smr(struct nameidata *ndp, struct vnode **vpp, bool *fsearch)
diff --git a/sys/sys/file.h b/sys/sys/file.h
index bc7dd7e06ded..d0b53196151e 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -267,6 +267,8 @@ int fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp,
     int needfcntl, struct file **fpp);
 int _fdrop(struct file *fp, struct thread *td);
 int fget_remote(struct thread *td, struct proc *p, int fd, struct file **fpp);
+int fget_remote_foreach(struct thread *td, struct proc *p,
+    int (*fn)(struct proc *, int, struct file *, void *), void *arg);
 
 fo_rdwr_t	invfo_rdwr;
 fo_truncate_t	invfo_truncate;