git: 713abc9880aa - main - sysctl(9): Ease exporting struct sizes; Discourage doing that

From: Olivier Certner <olce_at_FreeBSD.org>
Date: Wed, 07 May 2025 10:14:23 UTC
The branch main has been updated by olce:

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

commit 713abc9880aabe0ff924ff644bceb6ff404ed3cd
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2025-05-01 16:02:44 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2025-05-07 10:13:40 +0000

    sysctl(9): Ease exporting struct sizes; Discourage doing that
    
    Introduce two helpers, the more general SYSCTL_SIZEOF() and
    a struct-specific one SYSCTL_SIZEOF_STRUCT() which prepends 'struct' in
    the description and in the use of sizeof() but uses the raw structure
    name as the knob's name.  The size of the object/structure is exported
    under 'debug.sizeof'.
    
    Existing knobs under 'debug.sizeof' were all converted to use the
    helpers.
    
    Add a note before the helpers discouraging the introduction of new
    leaves for ad-hoc reasons.  List alternative means for developers to
    obtain the size of arbitrary kernel structures easily (thanks to markj@
    for providing these).
    
    No functional change (intended).
    
    Reviewed by:    kib, markj
    MFC after:      3 days
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D50121
---
 .../openzfs/module/os/freebsd/zfs/zfs_znode_os.c    |  4 ++++
 sys/fs/devfs/devfs_devs.c                           |  7 ++-----
 sys/geom/geom_kern.c                                | 15 +++++----------
 sys/kern/kern_mib.c                                 | 18 ++++++------------
 sys/kern/subr_devstat.c                             |  3 +--
 sys/kern/vfs_cache.c                                |  3 +--
 sys/sys/sysctl.h                                    | 21 +++++++++++++++++++++
 7 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode_os.c
index ce7b93d20a47..e97a0dd84040 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode_os.c
@@ -67,8 +67,12 @@
 #include "zfs_comutil.h"
 
 /* Used by fstat(1). */
+#ifdef SYSCTL_SIZEOF
+SYSCTL_SIZEOF(znode, znode_t);
+#else
 SYSCTL_INT(_debug_sizeof, OID_AUTO, znode, CTLFLAG_RD,
 	SYSCTL_NULL_INT_PTR, sizeof (znode_t), "sizeof(znode_t)");
+#endif
 
 /*
  * Define ZNODE_STATS to turn on statistic gathering. By default, it is only
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index c6dcd4fc7646..124f9f0449af 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -121,11 +121,8 @@ SYSCTL_PROC(_kern, OID_AUTO, devname,
     CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY|CTLFLAG_MPSAFE,
     NULL, 0, sysctl_devname, "", "devname(3) handler");
 
-SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct cdev), "sizeof(struct cdev)");
-
-SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev_priv, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct cdev_priv), "sizeof(struct cdev_priv)");
+SYSCTL_SIZEOF_STRUCT(cdev);
+SYSCTL_SIZEOF_STRUCT(cdev_priv);
 
 struct cdev *
 devfs_alloc(int flags)
diff --git a/sys/geom/geom_kern.c b/sys/geom/geom_kern.c
index 7f767da99dfc..c6ffd540bc9b 100644
--- a/sys/geom/geom_kern.c
+++ b/sys/geom/geom_kern.c
@@ -229,13 +229,8 @@ SYSCTL_INT(_kern_geom, OID_AUTO, collectstats, CTLFLAG_RW,
 	&g_collectstats, 0,
 	"Control statistics collection on GEOM providers and consumers");
 
-SYSCTL_INT(_debug_sizeof, OID_AUTO, g_class, CTLFLAG_RD,
-	SYSCTL_NULL_INT_PTR, sizeof(struct g_class), "sizeof(struct g_class)");
-SYSCTL_INT(_debug_sizeof, OID_AUTO, g_geom, CTLFLAG_RD,
-	SYSCTL_NULL_INT_PTR, sizeof(struct g_geom), "sizeof(struct g_geom)");
-SYSCTL_INT(_debug_sizeof, OID_AUTO, g_provider, CTLFLAG_RD,
-	SYSCTL_NULL_INT_PTR, sizeof(struct g_provider), "sizeof(struct g_provider)");
-SYSCTL_INT(_debug_sizeof, OID_AUTO, g_consumer, CTLFLAG_RD,
-	SYSCTL_NULL_INT_PTR, sizeof(struct g_consumer), "sizeof(struct g_consumer)");
-SYSCTL_INT(_debug_sizeof, OID_AUTO, g_bioq, CTLFLAG_RD,
-	SYSCTL_NULL_INT_PTR, sizeof(struct g_bioq), "sizeof(struct g_bioq)");
+SYSCTL_SIZEOF_STRUCT(g_class);
+SYSCTL_SIZEOF_STRUCT(g_geom);
+SYSCTL_SIZEOF_STRUCT(g_provider);
+SYSCTL_SIZEOF_STRUCT(g_consumer);
+SYSCTL_SIZEOF_STRUCT(g_bioq);
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index f8f90fce87cf..97742aefe8f7 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -730,11 +730,9 @@ SYSCTL_STRING(_user, USER_LOCALBASE, localbase, CTLFLAG_RWTUN,
     localbase, sizeof(localbase), "Prefix used to install and locate add-on packages");
 
 #include <sys/vnode.h>
-SYSCTL_INT(_debug_sizeof, OID_AUTO, vnode, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct vnode), "sizeof(struct vnode)");
+SYSCTL_SIZEOF_STRUCT(vnode);
 
-SYSCTL_INT(_debug_sizeof, OID_AUTO, proc, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct proc), "sizeof(struct proc)");
+SYSCTL_SIZEOF_STRUCT(proc);
 
 static int
 sysctl_kern_pid_max(SYSCTL_HANDLER_ARGS)
@@ -770,19 +768,15 @@ SYSCTL_INT(_kern, OID_AUTO, pid_max_limit, CTLFLAG_RD,
 
 #include <sys/bio.h>
 #include <sys/buf.h>
-SYSCTL_INT(_debug_sizeof, OID_AUTO, bio, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct bio), "sizeof(struct bio)");
-SYSCTL_INT(_debug_sizeof, OID_AUTO, buf, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct buf), "sizeof(struct buf)");
+SYSCTL_SIZEOF_STRUCT(bio);
+SYSCTL_SIZEOF_STRUCT(buf);
 
 #include <sys/user.h>
-SYSCTL_INT(_debug_sizeof, OID_AUTO, kinfo_proc, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct kinfo_proc), "sizeof(struct kinfo_proc)");
+SYSCTL_SIZEOF_STRUCT(kinfo_proc);
 
 /* Used by kernel debuggers. */
 const int pcb_size = sizeof(struct pcb);
-SYSCTL_INT(_debug_sizeof, OID_AUTO, pcb, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct pcb), "sizeof(struct pcb)");
+SYSCTL_SIZEOF_STRUCT(pcb);
 
 /* XXX compatibility, remove for 6.0 */
 #include <sys/imgact.h>
diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c
index f7e2595aa7cf..07a9cc0f57be 100644
--- a/sys/kern/subr_devstat.c
+++ b/sys/kern/subr_devstat.c
@@ -599,5 +599,4 @@ devstat_free(struct devstat *dsp)
 	}
 }
 
-SYSCTL_INT(_debug_sizeof, OID_AUTO, devstat, CTLFLAG_RD,
-    SYSCTL_NULL_INT_PTR, sizeof(struct devstat), "sizeof(struct devstat)");
+SYSCTL_SIZEOF_STRUCT(devstat);
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 9089c0fd78b4..ff671e80b803 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -627,8 +627,7 @@ SYSCTL_INT(_debug, OID_AUTO, vfscache, CTLFLAG_RW, &doingcache, 0,
 #endif
 
 /* Export size information to userland */
-SYSCTL_INT(_debug_sizeof, OID_AUTO, namecache, CTLFLAG_RD, SYSCTL_NULL_INT_PTR,
-    sizeof(struct namecache), "sizeof(struct namecache)");
+SYSCTL_SIZEOF_STRUCT(namecache);
 
 /*
  * The new name cache statistics
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 0eb9ff274c1b..902f5bde9c37 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -36,6 +36,7 @@
 #define	_SYS_SYSCTL_H_
 
 #ifdef _KERNEL
+#include <sys/cdefs.h>
 #include <sys/queue.h>
 #include <sys/tree.h>
 #endif
@@ -932,6 +933,26 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
 	    CTLFLAG_RD | CTLFLAG_CAPRD | CTLTYPE_INT | CTLFLAG_MPSAFE,	\
 	    NULL, 1, sysctl_handle_int, "I", desc, "feature");
 
+/*
+ * Adding new leaves to the 'debug.sizeof' MIB tree for ad-hoc reasons is
+ * discouraged, and in particular for reporting to developers the size of some
+ * kernel structures, which can be obtained by the following alternative means:
+ * 1. In GDB, load a full kernel image and use 'print(sizeof(struct XXX))'.
+ *    Alternatively, use 'ptype/o struct XXX' to additionally get the offsets
+ *    and size of all structure's fields.
+ * 2. If the structure is allocated from UMA, then 'vmstat -z' reports its size
+ *    (the mapping between structure types and zones is usually
+ *    straightforward).
+ */
+/* Generates a read-only sysctl reporting the size of an object/structure. */
+#define SYSCTL_SIZEOF(name, expr)					\
+	SYSCTL_INT(_debug_sizeof, OID_AUTO, name, CTLFLAG_RD,		\
+	    SYSCTL_NULL_INT_PTR, sizeof(expr),				\
+	    "sizeof(" __STRING(expr) ")");
+/* Same, specialized for structures. */
+#define SYSCTL_SIZEOF_STRUCT(struct_name)				\
+	SYSCTL_SIZEOF(struct_name, struct struct_name)
+
 #endif /* _KERNEL */
 
 /*