git: 593164975184 - main - eventfd: Add refcounting

From: Jean-Sébastien Pédron <dumbbell_at_FreeBSD.org>
Date: Sun, 25 Jan 2026 16:16:42 UTC
The branch main has been updated by dumbbell:

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

commit 5931649751847cc3ca54255bb767424dcb8a3e97
Author:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
AuthorDate: 2025-05-26 17:18:24 +0000
Commit:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
CommitDate: 2026-01-25 16:04:40 +0000

    eventfd: Add refcounting
    
    An eventfd file descriptor can be used by drivers such as DRM drivers
    through linuxkpi. A driver can hold a reference to such a file
    regardless of the fact it is used by userland or not.
    
    This patch introduces a refcount in `struct eventfd`, plus the
    `eventfd_get()` and `eventfd_put()` functions to acquire and release
    references. These functions will be used by DRM drivers for instance.
    
    This structure is internal to `sys/kern/sys_eventfd.c` and not used
    anywhere else. Thus it is safe to add a field without breaking anything.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D50849
---
 sys/kern/sys_eventfd.c | 30 ++++++++++++++++++++++++++++--
 sys/sys/eventfd.h      |  4 ++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/sys/kern/sys_eventfd.c b/sys/kern/sys_eventfd.c
index 04ed107c933d..433bcb57b2b3 100644
--- a/sys/kern/sys_eventfd.c
+++ b/sys/kern/sys_eventfd.c
@@ -40,6 +40,7 @@
 #include <sys/mutex.h>
 #include <sys/poll.h>
 #include <sys/proc.h>
+#include <sys/refcount.h>
 #include <sys/selinfo.h>
 #include <sys/stat.h>
 #include <sys/uio.h>
@@ -102,6 +103,7 @@ struct eventfd {
 	uint32_t	efd_flags;
 	struct selinfo	efd_sel;
 	struct mtx	efd_lock;
+	unsigned int	efd_refcount;
 };
 
 int
@@ -119,6 +121,7 @@ eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval,
 	efd->efd_count = initval;
 	mtx_init(&efd->efd_lock, "eventfd", NULL, MTX_DEF);
 	knlist_init_mtx(&efd->efd_sel.si_note, &efd->efd_lock);
+	refcount_init(&efd->efd_refcount, 1);
 
 	fflags = FREAD | FWRITE;
 	if ((flags & EFD_NONBLOCK) != 0)
@@ -128,16 +131,39 @@ eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval,
 	return (0);
 }
 
-static int
-eventfd_close(struct file *fp, struct thread *td)
+struct eventfd *
+eventfd_get(struct file *fp)
 {
 	struct eventfd *efd;
 
+	if (fp->f_data == NULL || fp->f_ops != &eventfdops)
+		return (NULL);
+
 	efd = fp->f_data;
+	refcount_acquire(&efd->efd_refcount);
+
+	return (efd);
+}
+
+void
+eventfd_put(struct eventfd *efd)
+{
+	if (!refcount_release(&efd->efd_refcount))
+		return;
+
 	seldrain(&efd->efd_sel);
 	knlist_destroy(&efd->efd_sel.si_note);
 	mtx_destroy(&efd->efd_lock);
 	free(efd, M_EVENTFD);
+}
+
+static int
+eventfd_close(struct file *fp, struct thread *td)
+{
+	struct eventfd *efd;
+
+	efd = fp->f_data;
+	eventfd_put(efd);
 	return (0);
 }
 
diff --git a/sys/sys/eventfd.h b/sys/sys/eventfd.h
index 0f64483753e5..1f36dbecb92d 100644
--- a/sys/sys/eventfd.h
+++ b/sys/sys/eventfd.h
@@ -38,8 +38,12 @@ typedef uint64_t eventfd_t;
 
 #ifdef _KERNEL
 
+struct eventfd;
+
 int eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval,
     int flags);
+struct eventfd *eventfd_get(struct file *fp);
+void eventfd_put(struct eventfd *efd);
 
 #else