[PATCH 03/11] moduleparam: Add DEFINE_KERNEL_PARAM_OPS macro family
Kees Cook
kees at kernel.org
Thu May 21 06:33:16 PDT 2026
Add macros that define a struct kernel_param_ops initializer through a
macro so the underlying field layout can evolve without touching every
call site. Three variants cover the three cases:
DEFINE_KERNEL_PARAM_OPS(name, set, get) // basic
DEFINE_KERNEL_PARAM_OPS_NOARG(name, set, get) // set KERNEL_PARAM_OPS_FL_NOARG
DEFINE_KERNEL_PARAM_OPS_FREE(name, set, get, free) // also set .free
Callers prefix their own visibility qualifiers, e.g.:
static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);
Also update module_param_call() and STANDARD_PARAM_DEF() to use
DEFINE_KERNEL_PARAM_OPS internally so the generated ops table will go
through the same macro as everything else.
Subsequent commits convert all open-coded struct kernel_param_ops
definitions to use these macros, in preparation for migrating to a
seq_buf .get API.
Signed-off-by: Kees Cook <kees at kernel.org>
---
include/linux/moduleparam.h | 36 ++++++++++++++++++++++++++++++++++--
kernel/params.c | 6 ++----
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 075f28585074..26bf45b36d02 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -68,6 +68,39 @@ struct kernel_param_ops {
void (*free)(void *arg);
};
+/*
+ * Define a const struct kernel_param_ops initializer. Callers prefix with
+ * any required visibility qualifiers (typically "static"):
+ *
+ * static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);
+ *
+ * Routing the @_set and @_get function pointers through the macro
+ * (rather than naming the struct fields at every call site) lets the
+ * field layout change in one place when callbacks are migrated to a
+ * new signature.
+ */
+#define DEFINE_KERNEL_PARAM_OPS(_name, _set, _get) \
+ const struct kernel_param_ops _name = { \
+ .set = (_set), \
+ .get = (_get), \
+ }
+
+/* As DEFINE_KERNEL_PARAM_OPS, with KERNEL_PARAM_OPS_FL_NOARG set. */
+#define DEFINE_KERNEL_PARAM_OPS_NOARG(_name, _set, _get) \
+ const struct kernel_param_ops _name = { \
+ .flags = KERNEL_PARAM_OPS_FL_NOARG, \
+ .set = (_set), \
+ .get = (_get), \
+ }
+
+/* As DEFINE_KERNEL_PARAM_OPS, with an additional .free callback. */
+#define DEFINE_KERNEL_PARAM_OPS_FREE(_name, _set, _get, _free) \
+ const struct kernel_param_ops _name = { \
+ .set = (_set), \
+ .get = (_get), \
+ .free = (_free), \
+ }
+
/*
* Flags available for kernel_param
*
@@ -311,8 +344,7 @@ struct kparam_array
* kernel_param_ops), use module_param_cb() instead.
*/
#define module_param_call(name, _set, _get, arg, perm) \
- static const struct kernel_param_ops __param_ops_##name = \
- { .flags = 0, .set = _set, .get = _get }; \
+ static DEFINE_KERNEL_PARAM_OPS(__param_ops_##name, _set, _get); \
__module_param_call(MODULE_PARAM_PREFIX, \
name, &__param_ops_##name, arg, perm, -1, 0)
diff --git a/kernel/params.c b/kernel/params.c
index 752721922a15..2cbad1f4dd06 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -222,10 +222,8 @@ char *parse_args(const char *doing,
return scnprintf(buffer, PAGE_SIZE, format "\n", \
*((type *)kp->arg)); \
} \
- const struct kernel_param_ops param_ops_##name = { \
- .set = param_set_##name, \
- .get = param_get_##name, \
- }; \
+ DEFINE_KERNEL_PARAM_OPS(param_ops_##name, \
+ param_set_##name, param_get_##name); \
EXPORT_SYMBOL(param_set_##name); \
EXPORT_SYMBOL(param_get_##name); \
EXPORT_SYMBOL(param_ops_##name)
--
2.34.1
More information about the linux-um
mailing list