git: f2a2e02ae54b - main - linuxkpi: Define `DEFINE_CLASS()` and `CLASS()`

From: Jean-Sébastien Pédron <dumbbell_at_FreeBSD.org>
Date: Wed, 09 Sep 2026 20:34:40 UTC
The branch main has been updated by dumbbell:

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

commit f2a2e02ae54b836d1e23648756a050406f65111e
Author:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
AuthorDate: 2026-06-12 17:56:35 +0000
Commit:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
CommitDate: 2026-09-09 20:01:30 +0000

    linuxkpi: Define `DEFINE_CLASS()` and `CLASS()`
    
    `DEFINE_CLASS()` is in fact named `LINUXKPI_DEFINE_CLASS()` because it
    conflicts with `DEFINE_CLASS()` defined in <sys/kobj.h>.
    
    This macro defines a type and a pair of constructor/destructor
    functions.
    
    They are to be used by `CLASS()`: this one declares a variable,
    initialise it with the constructor and set the `__cleanup()` attribute
    to call the destructor once the variable goes out of scope.
    
    The DRM drivers generic code started to use `CLASS()` in Linux 6.13. It
    requires the `fd` class to be defined in <linux/file.h>.
    
    Reviewed by:    bz
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D57583
---
 sys/compat/linuxkpi/common/include/linux/cleanup.h | 26 ++++++++++++++++++++++
 sys/compat/linuxkpi/common/include/linux/file.h    |  2 ++
 2 files changed, 28 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h
index fb21a81f121b..815cdc37a956 100644
--- a/sys/compat/linuxkpi/common/include/linux/cleanup.h
+++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h
@@ -20,6 +20,32 @@
     CLEANUP_NAME(_n, _t) _x __cleanup(CLEANUP_NAME(_n, _destroy)) =	\
 	CLEANUP_NAME(_n, _create)
 
+/*
+ * On Linux, the following macro is called `DEFINE_CLASS()`. However it
+ * conflicts with FreeBSD's macro defined in <sys/kobj.h>.
+ *
+ * Note: "_T" are special as they are exposed into common code for
+ * statements.  Extra care should be taken when changing the code.
+ */
+#define	LINUXKPI_DEFINE_CLASS(_name, _type, _exit, _init, _init_args...)\
+    typedef _type class_##_name##_t;					\
+									\
+    static inline _type class_##_name##_constructor(_init_args)		\
+    {									\
+	_type v = _init;						\
+	return (v);							\
+    }									\
+									\
+    static inline void class_##_name##_destructor(_type *p)		\
+    {									\
+	_type _T = *p;							\
+	_exit;								\
+    }
+
+#define	CLASS(_name, _var)						\
+    class_##_name##_t _var __cleanup(class_##_name##_destructor) =	\
+	class_##_name##_constructor
+
 /*
  * Note: "_T" are special as they are exposed into common code for
  * statements.  Extra care should be taken when changing the code.
diff --git a/sys/compat/linuxkpi/common/include/linux/file.h b/sys/compat/linuxkpi/common/include/linux/file.h
index 13eecfa6a2b0..6ed480f4356a 100644
--- a/sys/compat/linuxkpi/common/include/linux/file.h
+++ b/sys/compat/linuxkpi/common/include/linux/file.h
@@ -184,6 +184,8 @@ static inline struct fd fdget(unsigned int fd)
 	return (struct fd){f};
 }
 
+LINUXKPI_DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)
+
 #define	fd_file(fd)	((fd).linux_file)
 
 static inline bool