git: cd349e1bcd21 - stable/15 - procdesc: track count of open files

Konstantin Belousov <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a81248a.447af.47045d46__22292.9198456526$1786848523$gmane$org@gitrepo.freebsd.org>
The branch stable/15 has been updated by kib:

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

commit cd349e1bcd21bbf9fd8834550cb6b8305977472c
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-05-21 00:47:20 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-08-16 02:41:21 +0000

    procdesc: track count of open files
    
    (cherry picked from commit 18b6bb5231bf1c927a6f8de24e466764fe1f7470)
---
 sys/kern/kern_exit.c    |  4 ++--
 sys/kern/sys_procdesc.c | 17 +++++++++++------
 sys/sys/procdesc.h      |  4 +++-
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index b20009f46139..73c5a6f9f224 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1577,8 +1577,8 @@ kern_pdwait(struct thread *td, int fd, int *status,
 
 	for (;;) {
 		/* We own a reference on the procdesc file. */
-		KASSERT((pd->pd_flags & PDF_CLOSED) == 0,
-		    ("PDF_CLOSED proc %p procdesc %p pd flags %#x",
+		KASSERT(pd->pd_fpcount > 0,
+		    ("closed proc %p procdesc %p pd flags %#x",
 		    p, pd, pd->pd_flags));
 
 		sx_xlock(&proctree_lock);
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 3c99f0241016..a3e234be7e39 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -219,6 +219,7 @@ procdesc_alloc(int flags)
 	 * struct file, and the other from their struct proc.
 	 */
 	refcount_init(&pd->pd_refcount, 2);
+	pd->pd_fpcount = 1;
 
 	return (pd);
 }
@@ -293,8 +294,8 @@ procdesc_free(struct procdesc *pd)
 	if (refcount_release(&pd->pd_refcount)) {
 		KASSERT(pd->pd_proc == NULL,
 		    ("procdesc_free: pd_proc != NULL"));
-		KASSERT((pd->pd_flags & PDF_CLOSED),
-		    ("procdesc_free: !PDF_CLOSED"));
+		KASSERT(pd->pd_fpcount == 0,
+		    ("procdesc_free: not closed %p %d", pd, pd->pd_fpcount));
 
 		if (pd->pd_pid != -1)
 			proc_id_clear(PROC_ID_PID, pd->pd_pid);
@@ -322,7 +323,7 @@ procdesc_exit(struct proc *p)
 	pd = p->p_procdesc;
 
 	PROCDESC_LOCK(pd);
-	KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == p->p_reaper,
+	KASSERT(pd->pd_fpcount > 0 || p->p_pptr == p->p_reaper,
 	    ("procdesc_exit: closed && parent not reaper"));
 
 	pd->pd_flags |= PDF_EXITED;
@@ -334,7 +335,7 @@ procdesc_exit(struct proc *p)
 	 * Clean up the procdesc now rather than letting it happen during
 	 * that reap.
 	 */
-	if (pd->pd_flags & PDF_CLOSED) {
+	if (pd->pd_fpcount == 0) {
 		PROCDESC_UNLOCK(pd);
 		pd->pd_proc = NULL;
 		p->p_procdesc = NULL;
@@ -388,7 +389,8 @@ procdesc_close(struct file *fp, struct thread *td)
 
 	sx_xlock(&proctree_lock);
 	PROCDESC_LOCK(pd);
-	pd->pd_flags |= PDF_CLOSED;
+	MPASS(pd->pd_fpcount > 0);
+	pd->pd_fpcount--;
 	PROCDESC_UNLOCK(pd);
 	p = pd->pd_proc;
 	if (p == NULL) {
@@ -408,7 +410,7 @@ procdesc_close(struct file *fp, struct thread *td)
 			 * calls back into procdesc_reap().
 			 */
 			proc_reap(curthread, p, NULL, 0);
-		} else {
+		} else if (pd->pd_fpcount == 0) /* last procdesc */ {
 			/*
 			 * If the process is not yet dead, we need to kill it,
 			 * but we can't wait around synchronously for it to go
@@ -438,6 +440,9 @@ procdesc_close(struct file *fp, struct thread *td)
 				kern_psignal(p, SIGKILL);
 			PROC_UNLOCK(p);
 			sx_xunlock(&proctree_lock);
+		} else {
+			PROC_UNLOCK(p);
+			sx_xunlock(&proctree_lock);
 		}
 	}
 
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
index a6be5dbe576c..08b563828b95 100644
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -51,6 +51,8 @@
  * (r) - Atomic reference count.
  * (s) - Protected by selinfo.
  * (t) - Protected by the proctree_lock
+ * (p|t) - Both procree_lock and process descriptor must be locked
+ *	 for pd_fpcount
  */
 struct proc;
 struct sigio;
@@ -63,6 +65,7 @@ struct procdesc {
 	struct proc	*pd_proc;		/* (t) Process. */
 	pid_t		 pd_pid;		/* (c) Cached pid. */
 	u_int		 pd_refcount;		/* (r) Reference count. */
+	u_int		 pd_fpcount;		/* (p|t) files referencing me */
 
 	/*
 	 * In-flight data and notification of events.
@@ -85,7 +88,6 @@ struct procdesc {
 /*
  * Flags for the pd_flags field.
  */
-#define	PDF_CLOSED	0x00000001	/* Descriptor has closed. */
 #define	PDF_EXITED	0x00000004	/* Process exited. */
 #define	PDF_DAEMON	0x00000008	/* Don't exit when procdesc closes. */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.