sysctl: refactor ctl_table initialization
v4 cover sysctl: refactor ctl_table initialization
From: Wen Yang <[email protected]>
The main motivation for this series is to avoid treewide patch series. Historically, changes to how struct ctl_table entries are initialized (e.g. removing the child field, const-qualifying ctl_table) required touching hundreds of files across all subsystems. Such series require the attention of many maintainers, sometimes need to be pulled into mainline in a special way, and create lots of unnecessary churn.
By introducing a family of CTLTBL_ENTRY_XXX() helper macros in <linux/sysctl.h>, any future structural changes to struct ctl_table can be handled in one place — the macro definition — without requiring a treewide sweep of all callers. Individual subsystem maintainers can also migrate their sysctl tables to use the macros at their own pace.
Based on discussion and suggestions from:
[1] https://sysctl-dev-rtd.readthedocs.io/en/latest/notes/ctltable_entry_macro.html#table-entry-macro
[2] https://lore.kernel.org/all/psot4oeauxi3yyj2w4ajm3tfgtcsvao4rhv5sgd5s6ymmjgojk@p3vrj3qluban/
This series:
1. Introduces the CTLTBL_ENTRY_XXX() macros in include/linux/sysctl.h, allowing callers to initialize struct ctl_table entries indirectly via the macro instead of assigning each field directly. The macros use _Generic() for automatic type detection and proc_handler selection, provide smart defaults (auto address-of, auto maxlen via sizeof), and include compile-time validation of name, mode, and handler.
2. Converts kernel/sysctl-test.c to use the new macros as a demonstration, replacing direct struct ctl_table field assignments with CTLTBL_ENTRY_XXX() calls. Four new tests are added to cover the previously untested variants (CTLTBL_ENTRY_V, VN, VNM, VNMH), bringing the total to 16 passing tests.
---
Changes in v4:
- Fix Wpointer-type-mismatch warnings detected by lkp:
https://lore.kernel.org/oe-kbuild-all/[email protected]/
Changes in v3:
- replace the unique macro with "capital letter approach"
- reduce the name further
https://lore.kernel.org/all/rn4rsazh7kxf5byq65vw2phyqgzvwm3scczu3l5h2r4aqit2r6@znlpb24z2zuo/
Changes in v2:
- add lvalue check, handler type check, etc.
https://lore.kernel.org/all/xptwb3uwbzposd4xf7khj52ifv4tchcjdgllhv7aabi6d7wgef@2msurl564v53/
Wen Yang (2):
sysctl: introduce CTLTBL_ENTRY_XXX() helper macros
sysctl: convert kernel/sysctl-test.c to use CTLTBL_ENTRY_XXX()
include/linux/sysctl.h | 294 +++++++++++++++++++++++++++++++++++++++++ kernel/sysctl-test.c | 240 +++++++++++++++++++-------------- kernel/sysctl.c | 2 + 3 files changed, 437 insertions(+), 99 deletions(-)
Signature · 1 line
2.25.1
RFC PATCH v4 1/2 sysctl: introduce CTLTBL_ENTRY_XXX() helper macros
From: Wen Yang <[email protected]>
Add a family of CTLTBL_ENTRY_XXX() macros to simplify struct ctl_table initialization. Each macro variant covers a different use case, using _Generic() for automatic type detection and proc_handler selection, with sensible defaults to reduce boilerplate and potential errors.
The following macro variants are introduced:
CTLTBL_ENTRY_V(__var)
- Uses variable name as procname, mode 0444, and auto-selected handler based on variable type
CTLTBL_ENTRY_VM(__var, __mode)
- Uses variable name as procname, custom mode, and auto-selected handler based on variable type
CTLTBL_ENTRY_VMR(__var, __mode, __min, __max)
- Uses variable name as procname, custom mode,
and auto-selected range-checking handler based on variable type
CTLTBL_ENTRY_VN(__var, __name)
- Custom procname, mode 0444,
and auto-selected handler based on variable type
CTLTBL_ENTRY_VNM(__var, __name, __mode)
- Custom procname and mode,
and auto-selected handler based on variable type
CTLTBL_ENTRY_VNMH(__var, __name, __mode, __handler)
- Custom procname, mode, and proc_handler
CTLTBL_ENTRY_VNMR(__var, __name, __mode, __min, __max)
- Auto-selected range-checking handler based on variable type
CTLTBL_ENTRY_VNMHR(__var, __name, __mode, __handler, __min, __max)
- Custom handler with extra1/extra2 range bounds
CTLTBL_ENTRY_VNMHRL(__var, __name, __mode, __handler, __min, __max, __maxlen)
- Full control including explicit maxlen override
All variants share the following features:
- Automatic type detection via _Generic(): supports int, unsigned int, long, unsigned long; selects the appropriate proc_dointvec, proc_douintvec, or proc_doulongvec_minmax handler automatically
- Auto address-of: the macro takes the address of the variable, so callers do not need to pass &var explicitly
- Auto maxlen: uses sizeof(var) when maxlen is not explicitly provided
- SYSCTL_NULL marker: use SYSCTL_NULL as the variable argument for entries where .data should be NULL
- Compile-time validation: NAME must be a string literal; MODE and HANDLER are checked for type compatibility
No functional change intended.
--- include/linux/sysctl.h | 294 +++++++++++++++++++++++++++++++++++++++++ kernel/sysctl.c | 2 + 2 files changed, 296 insertions(+)
include/linux/sysctl.h +294 -0
@@ -175,6 +175,300 @@ struct ctl_table {void *extra2; } __randomize_layout; +/** +* struct _sysctl_null_type - sentinel type for variable-less entries +*/ +struct _sysctl_null_type {char __dummy; }; + +/** +* _sysctl_null_marker - unique instance of the sentinel type +* +* Define once per link unit: +* const struct _sysctl_null_type _sysctl_null_marker; +*/ +extern const struct _sysctl_null_type _sysctl_null_marker; + +/** +* SYSCTL_NULL - pass as __var for entries with no associated variable +*/ +#define SYSCTL_NULL (_sysctl_null_marker) + +/** +* __CTL_AUTO_HANDLER - select proc_handler based on the variable type +* @__var: kernel variable (value, not address), or SYSCTL_NULL +*/ +#define __CTL_AUTO_HANDLER (__var) \ + _Generic((__var), \ + int : proc_dointvec, \ + unsigned int : proc_douintvec, \ + long : proc_doulongvec_minmax, \ + unsigned long : proc_doulongvec_minmax, \ + default : \ + 0xdeadbeaf) + +/** +* __CTL_AUTO_HANDLER_RANGE - select proc_handler for a range-constrained entry +* @__var: kernel variable (value, not address), or SYSCTL_NULL +*/ +#define __CTL_AUTO_HANDLER_RANGE (__var) \ + _Generic((__var), \ + int : proc_dointvec_minmax, \ + unsigned int : proc_douintvec_minmax, \ + long : proc_doulongvec_minmax, \ + unsigned long : proc_doulongvec_minmax, \ + default : \ + 0xdeadbeaf) + +/** +* __CTL_PROCNAME - validate and return the procname string +* +* "" __name "" enforces a string-literal argument at compile time. +* +* @__name: procname string literal +*/ +#define __CTL_PROCNAME (__name) ("" __name "") + +/** +* __CTL_DATA - assert __var is addressable; return its address +* +* SYSCTL_NULL -> (void *)NULL +* lvalue __var -> (void *)&(__var) +* +* @__var: kernel variable (without &), or SYSCTL_NULL +*/ +#define __CTL_DATA (__var) \ + _Generic((__var), \ + struct _sysctl_null_type : (void *)NULL, \ + default : \ + (void *)&(__var)) + +/* Compute maxlen for NULL entries: use explicit MAXLEN if >0, else 0 */ +#define __SYSCTL_MAXLEN_NULL (__maxlen) \ + ((__maxlen) > 0 ? (size_t)(__maxlen) : (size_t)0) + +/* Compute maxlen: use explicit MAXLEN if >0, else sizeof(VAR) */ +#define __SYSCTL_MAXLEN_VAR (__var, __maxlen) \ + ((__maxlen) >= 0 ? (size_t)(__maxlen) : (size_t)sizeof(__var)) + +/** +* __CTL_MAXLEN - compute the .maxlen value +* +* @__var: kernel variable (without &), or SYSCTL_NULL +* @__maxlen: explicit override, or -1 for auto-sizing +*/ +#define __CTL_MAXLEN (__var, __maxlen) \ + _Generic((__var), \ + struct _sysctl_null_type : \ + __SYSCTL_MAXLEN_NULL(__maxlen), \ + default : \ + __SYSCTL_MAXLEN_VAR(__var, __maxlen) \ + ) + +/** +* __CTL_MODE - validate and return file permission bits +* +* @__mode: file permission bits (e.g. 0644) +*/ +#define __CTL_MODE (__mode) (0 ? (umode_t)0 : (__mode)) + +/** +* __CTL_HANDLER - validate and return proc_handler +* +* @__handler: proc_handler +*/ +#define __CTL_HANDLER (__handler) \ + (0 ? (typeof(proc_handler) *)0 : (__handler)) + +/* Validate PTR is pointer-compatible and return it as void* */ +#define __CTL_EXTRA (PTR ) \ + (0 ? (void *)0 : (PTR)) + +/** +* Internal primitive (single source of truth) +* +* All public macros delegate here. +* +* @_var: kernel variable (without &), or SYSCTL_NULL +* @_name: procname string literal +* @_mode: file permission bits +* @_handler: proc_handler-compatible function pointer +* @_min: lower bound pointer, or NULL +* @_max: upper bound pointer, or NULL +* @_maxlen: explicit .maxlen, or -1 for auto-sizing +*/ +#define __CTLTBL_ENTRY (_var, _name, _mode, _handler, _min, _max, _maxlen) \ +{ \ + .procname = __CTL_PROCNAME(_name), \ + .data = __CTL_DATA(_var), \ + .maxlen = __CTL_MAXLEN(_var, _maxlen), \ + .mode = __CTL_MODE(_mode), \ + .proc_handler = __CTL_HANDLER(_handler), \ + .poll = NULL, \ + .extra1 = __CTL_EXTRA(_min), \ + .extra2 = __CTL_EXTRA(_max), \ +} + +/** +* Public API +* +* Naming convention: +* V - Variable is auto-named via #__var +* N - explicit Name string +* M - explicit Mode +* H - explicit Handler +* R - Range checking (min/max, selects _minmax handler) +* L - explicit Length (.maxlen override) +*/ + +/** +* CTLTBL_ENTRY_V - read-only entry; procname == stringified variable name +* +* Proto: (T __var) +* +* .procname = #__var, .mode = 0444, .extra1 = .extra2 = NULL. +* proc_handler and .maxlen inferred from typeof(__var). +* +* @__var: kernel variable (without &); must be an addressable lvalue +*/ +#define CTLTBL_ENTRY_V (__var) \ + __CTLTBL_ENTRY(__var, #__var, 0444, \ + __CTL_AUTO_HANDLER(__var), NULL, NULL, -1) + +/** +* CTLTBL_ENTRY_VM - entry with custom mode; procname == #__var +* +* Proto: (T __var, umode_t __mode) +* +* @__var: kernel variable (without &) +* @__mode: file permission bits +*/ +#define CTLTBL_ENTRY_VM (__var, __mode) \ + __CTLTBL_ENTRY(__var, #__var, __mode, \ + __CTL_AUTO_HANDLER(__var), NULL, NULL, -1) + +/** +* CTLTBL_ENTRY_VMR - custom mode with range checking; procname == #__var +* +* Proto: (T __var, umode_t __mode, T *__min, T *__max) +* +* @__var: kernel variable (without &) +* @__mode: file permission bits +* @__min: pointer to minimum value; typeof(*__min) must == typeof(__var) +* @__max: pointer to maximum value; typeof(*__max) must == typeof(__var) +*/ +#define CTLTBL_ENTRY_VMR (__var, __mode, __min, __max) \ + __CTLTBL_ENTRY(__var, #__var, __mode, \ + __CTL_AUTO_HANDLER_RANGE(__var), __min, __max, -1) + +/** +* CTLTBL_ENTRY_VN - read-only entry with explicit procname +* +* Proto: (T __var, const char *__name) +* +* @__var: kernel variable (without &) +* @__name: procname string literal +*/ +#define CTLTBL_ENTRY_VN (__var, __name) \ + __CTLTBL_ENTRY(__var, __name, 0444, \ + __CTL_AUTO_HANDLER(__var), NULL, NULL, -1) + +/** +* CTLTBL_ENTRY_VNM - entry with explicit procname and mode +* +* Proto: (T __var, const char *__name, umode_t __mode) +* +* @__var: kernel variable (without &) +* @__name: procname string literal +* @__mode: file permission bits +*/ +#define CTLTBL_ENTRY_VNM (__var, __name, __mode) \ + __CTLTBL_ENTRY(__var, __name, __mode, \ + __CTL_AUTO_HANDLER(__var), NULL, NULL, -1) + +/** +* CTLTBL_ENTRY_VNMH - entry with explicit procname, mode and handler +* +* Proto: (T __var, const char *__name, umode_t __mode, +* proc_handler *__handler) +* +* @__var: kernel variable (without &), or SYSCTL_NULL +* @__name: procname string literal +* @__mode: file permission bits +* @__handler: proc_handler-compatible function pointer +*/ +#define CTLTBL_ENTRY_VNMH (__var, __name, __mode, __handler) \ + __CTLTBL_ENTRY(__var, __name, __mode, __handler, NULL, NULL, -1) + +/** +* CTLTBL_ENTRY_VNMR - entry with procname, mode and range checking +* +* Proto: (T __var, const char *__name, umode_t __mode, +* T *__min, T *__max) +* +* @__var: kernel variable (without &) +* @__name: procname string literal +* @__mode: file permission bits +* @__min: pointer to minimum value; typeof(*__min) must == typeof(__var) +* @__max: pointer to maximum value; typeof(*__max) must == typeof(__var) +*/ +#define CTLTBL_ENTRY_VNMR (__var, __name, __mode, __min, __max) \ + __CTLTBL_ENTRY(__var, __name, __mode, \ + __CTL_AUTO_HANDLER_RANGE(__var), __min, __max, -1) + +/** +* CTLTBL_ENTRY_VNMHR - entry with explicit handler and range +* +* Proto: (T __var, const char *__name, umode_t __mode, +* proc_handler *__handler, T *__min, T *__max) +* +* @__var: kernel variable (without &), or SYSCTL_NULL +* @__name: procname string literal +* @__mode: file permission bits +* @__handler: proc_handler-compatible function pointer +* @__min: pointer to minimum value for .extra1 +* @__max: pointer to maximum value for .extra2 +*/ +#define CTLTBL_ENTRY_VNMHR (__var, __name, __mode, __handler, __min, __max) \ + __CTLTBL_ENTRY(__var, __name, __mode, __handler, __min, __max, -1) + +/** +* CTLTBL_ENTRY_VNMHRL - fully explicit entry +* +* Proto: (T __var, const char *__name, umode_t __mode, +* proc_handler *__handler, T *__min, T *__max, +* size_t __maxlen) +* +* Pass -1 for __maxlen to use sizeof(__var) / 0 (auto). +* Pass 0 to set .maxlen to zero explicitly. +* +* @__var: kernel variable (without &), or SYSCTL_NULL +* @__name: procname string literal +* @__mode: file permission bits +* @__handler: proc_handler-compatible function pointer +* @__min: pointer to minimum value for .extra1 +* @__max: pointer to maximum value for .extra2 +* @__maxlen: explicit value for .maxlen +*/ +#define CTLTBL_ENTRY_VNMHRL (__var, __name, __mode, __handler, \ + __min, __max, __maxlen) \ + __CTLTBL_ENTRY(__var, __name, __mode, __handler, __min, __max, __maxlen) + +/** +* CTLTBL_ENTRY_NMH - custom-handler entry with no associated variable +* +* Proto: (const char *__name, umode_t __mode, +* proc_handler *__handler) +* +* Shorthand for CTLTBL_ENTRY_VNMH(SYSCTL_NULL, ...). +* .data = NULL, .maxlen = 0, .extra1 = NULL, .extra2 = NULL. +* +* @__name: procname string literal +* @__mode: file permission bits +* @__handler: proc_handler-compatible function pointer +*/ +#define CTLTBL_ENTRY_NMH (__name, __mode, __handler) \ + CTLTBL_ENTRY_VNMH(SYSCTL_NULL, __name, __mode, __handler) +struct ctl_node {struct rb_node node;struct ctl_table_header *header;
kernel/sysctl.c +2 -0
@@ -29,6 +29,8 @@ EXPORT_SYMBOL(sysctl_vals);const unsigned long sysctl_long_vals[] = {0 ,1 ,LONG_MAX };EXPORT_SYMBOL_GPL (sysctl_long_vals); +const struct _sysctl_null_type _sysctl_null_marker; +#if defined(CONFIG_SYSCTL )/* Constants used for minimum and maximum */
Signature · 1 line
2.25.1
RFC PATCH v4 2/2 sysctl: convert kernel/sysctl-test.c to use CTLTBL_ENTRY_XXX()
In reply to [email protected]From: Wen Yang <[email protected]>
Convert all struct ctl_table initializations in kernel/sysctl-test.c from direct field assignment to indirect initialization via the CTLTBL_ENTRY_XXX() macros introduced in the previous patch. This demonstrates the macros in real usage and validates their correctness against the existing test suite.
The following macro variants are exercised:
- CTLTBL_ENTRY_VNMR(var, name, mode, min, max)
Used for the majority of test cases that initialize a standard int entry with range checking. The macro automatically selects the range-checking handler (proc_dointvec_minmax for int) based on the variable type and computes maxlen via sizeof():
Before:
struct ctl_table table = {
.procname = "foo",
.data = &data,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE_HUNDRED,
};
After:
struct ctl_table table = CTLTBL_ENTRY_VNMR(data, "foo", 0644,
SYSCTL_ZERO, SYSCTL_ONE_HUNDRED);
- CTLTBL_ENTRY_VNMHR(var, name, mode, handler, min, max) Used for the NULL data test case, passing SYSCTL_NULL as the data argument and proc_dointvec as the explicit handler:
Before:
struct ctl_table null_data_table = {
.procname = "foo",
.data = NULL,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE_HUNDRED,
};
After:
struct ctl_table null_data_table = CTLTBL_ENTRY_VNMHR(
SYSCTL_NULL, "foo", 0644, proc_dointvec, SYSCTL_ZERO, SYSCTL_ONE_HUNDRED);
- CTLTBL_ENTRY_VNMHRL(var, name, mode, handler, min, max, maxlen) Used for the maxlen=0 test case, passing an explicit maxlen of 0 to override the default sizeof()-based value:
Before:
struct ctl_table data_maxlen_unset_table = {
.procname = "foo",
.data = &data,
.maxlen = 0,
.mode = 0644,
.proc_handler = proc_dointvec,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE_HUNDRED,
};
After:
struct ctl_table data_maxlen_unset_table = CTLTBL_ENTRY_VNMHRL(
data, "foo", 0644, proc_dointvec, SYSCTL_ZERO, SYSCTL_ONE_HUNDRED, 0);
New tests are added to cover the remaining macro variants:
- CTLTBL_ENTRY_V(var)
Verifies that the macro initializes .procname to the variable name, .mode to 0444, .data to &var, .maxlen to sizeof(var), and selects proc_dointvec as the handler for an int variable.
- CTLTBL_ENTRY_VM(var, mode)
Verifies that the macro initializes .procname to the variable name, .mode to 0644, .data to &var, .maxlen to sizeof(var), and selects proc_dointvec as the handler for an int variable.
- CTLTBL_ENTRY_VMR(var, mode, min, max)
Verifies that the macro initializes .procname to the variable name, .mode to 0644, .data to &var, .maxlen to sizeof(var), and auto-selecting proc_dointvec_minmax as the handler.
- CTLTBL_ENTRY_VN(var, name)
Verifies that the macro initializes .procname to the custom name while keeping .mode at 0444 and auto-selecting the handler.
- CTLTBL_ENTRY_VNM(name, var, mode)
Verifies that the macro initializes .procname and .mode as specified while auto-selecting the handler.
- CTLTBL_ENTRY_VNMH(var, name, mode, handler)
Verifies that the macro initializes all fields including an explicitly provided proc_handler.
All tests pass:
[13:53:49] ================ sysctl_test (16 subtests) ================= [13:53:49] [PASSED] sysctl_test_api_dointvec_null_tbl_data [13:53:49] [PASSED] sysctl_test_api_dointvec_table_maxlen_unset [13:53:49] [PASSED] sysctl_test_api_dointvec_table_len_is_zero [13:53:49] [PASSED] sysctl_test_api_dointvec_table_read_but_position_set [13:53:49] [PASSED] sysctl_test_dointvec_read_happy_single_positive [13:53:49] [PASSED] sysctl_test_dointvec_read_happy_single_negative [13:53:49] [PASSED] sysctl_test_dointvec_write_happy_single_positive [13:53:49] [PASSED] sysctl_test_dointvec_write_happy_single_negative [13:53:49] [PASSED] sysctl_test_api_dointvec_write_single_less_int_min [13:53:49] [PASSED] sysctl_test_api_dointvec_write_single_greater_int_max [13:53:49] [PASSED] sysctl_test_api_ctltbl_entry_v
[13:53:49] [PASSED] sysctl_test_api_ctltbl_entry_vm [13:53:49] [PASSED] sysctl_test_api_ctltbl_entry_vmr [13:53:49] [PASSED] sysctl_test_api_ctltbl_entry_vn [13:53:49] [PASSED] sysctl_test_api_ctltbl_entry_vnm [13:53:49] [PASSED] sysctl_test_api_ctltbl_entry_vnmh [13:53:49] =================== [PASSED] sysctl_test =================== [13:53:49] ============================================================ [13:53:49] Testing complete. Ran 16 tests: passed: 16
--- kernel/sysctl-test.c | 240 +++++++++++++++++++++++++------------------ 1 file changed, 141 insertions(+), 99 deletions(-)
kernel/sysctl-test.c +141 -99
@@ -15,20 +15,14 @@*/ static void sysctl_test_api_dointvec_null_tbl_data (struct kunit *test) { -struct ctl_table null_data_table = { - .procname ="foo" , -/* -* Here we are testing that proc_dointvec behaves correctly when -* we give it a NULL .data field. Normally this would point to a -* piece of memory where the value would be stored. -*/ - .data =NULL , - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +/* +* Here we are testing that proc_dointvec behaves correctly when +* we give it a NULL .data field. Normally this would point to a +* piece of memory where the value would be stored. +*/ +struct ctl_table null_data_table =CTLTBL_ENTRY_VNMHR ( +SYSCTL_NULL ,"foo" ,0644 , proc_dointvec, +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );/* * proc_dointvec expects a buffer in user space, so we allocate one. We * also need to cast it to __user so sparse doesn't get mad.
@@ -66,19 +60,14 @@ static void sysctl_test_api_dointvec_null_tbl_data(struct kunit *test)static void sysctl_test_api_dointvec_table_maxlen_unset (struct kunit *test) {int data =0 ; -struct ctl_table data_maxlen_unset_table = { - .procname ="foo" , - .data = &data, -/* -* So .data is no longer NULL, but we tell proc_dointvec its -* length is 0, so it still shouldn't try to use it. -*/ - .maxlen =0 , - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +/* +* So .data is no longer NULL, but we tell proc_dointvec its +* length is 0, so it still shouldn't try to use it. +*/ +struct ctl_table data_maxlen_unset_table =CTLTBL_ENTRY_VNMHRL ( + data,"foo" ,0644 , proc_dointvec, +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED ,0 ); +void __user *buffer = (void __user *)kunit_kzalloc (test,sizeof (int ),GFP_USER );size_t len;
@@ -113,15 +102,8 @@ static void sysctl_test_api_dointvec_table_len_is_zero(struct kunit *test) {int data =0 ;/* Good table. */ -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" , +0644 ,SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );void __user *buffer = (void __user *)kunit_kzalloc (test,sizeof (int ),GFP_USER );/*
@@ -147,15 +129,8 @@ static void sysctl_test_api_dointvec_table_read_but_position_set( {int data =0 ;/* Good table. */ -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );void __user *buffer = (void __user *)kunit_kzalloc (test,sizeof (int ),GFP_USER );/*
@@ -182,15 +157,8 @@ static void sysctl_test_dointvec_read_happy_single_positive(struct kunit *test) {int data =0 ;/* Good table. */ -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );size_t len =4 ;loff_t pos =0 ;char *buffer =kunit_kzalloc (test, len,GFP_USER );
@@ -213,15 +181,8 @@ static void sysctl_test_dointvec_read_happy_single_negative(struct kunit *test) {int data =0 ;/* Good table. */ -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );size_t len =5 ;loff_t pos =0 ;char *buffer =kunit_kzalloc (test, len,GFP_USER );
@@ -242,15 +203,8 @@ static void sysctl_test_dointvec_write_happy_single_positive(struct kunit *test) {int data =0 ;/* Good table. */ -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );char input[] ="9" ;size_t len =sizeof (input) -1 ;loff_t pos =0 ;
@@ -272,15 +226,8 @@ static void sysctl_test_dointvec_write_happy_single_positive(struct kunit *test)static void sysctl_test_dointvec_write_happy_single_negative (struct kunit *test) {int data =0 ; -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );char input[] ="-9" ;size_t len =sizeof (input) -1 ;loff_t pos =0 ;
@@ -304,15 +251,8 @@ static void sysctl_test_api_dointvec_write_single_less_int_min( struct kunit *test) {int data =0 ; -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );size_t max_len =32 , len = max_len;loff_t pos =0 ;char *buffer =kunit_kzalloc (test, max_len,GFP_USER );
@@ -342,15 +282,8 @@ static void sysctl_test_api_dointvec_write_single_greater_int_max( struct kunit *test) {int data =0 ; -struct ctl_table table = { - .procname ="foo" , - .data = &data, - .maxlen =sizeof (int ), - .mode =0644 , - .proc_handler = proc_dointvec, - .extra1 =SYSCTL_ZERO , - .extra2 =SYSCTL_ONE_HUNDRED , - }; +struct ctl_table table =CTLTBL_ENTRY_VNMR (data,"foo" ,0644 , +SYSCTL_ZERO ,SYSCTL_ONE_HUNDRED );size_t max_len =32 , len = max_len;loff_t pos =0 ;char *buffer =kunit_kzalloc (test, max_len,GFP_USER );
@@ -367,6 +300,109 @@ static void sysctl_test_api_dointvec_write_single_greater_int_max(KUNIT_EXPECT_EQ (test,0 , *((int *)table.data)); } +/* +* Test CTLTBL_ENTRY_V: variable name used as procname, mode 0444, +* auto-selected handler (proc_dointvec for int). +*/ +static void sysctl_test_api_ctltbl_entry_v (struct kunit *test) +{ +int foo =123 ; +struct ctl_table table =CTLTBL_ENTRY_V (foo); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0444 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &foo, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} + +/* +* Test CTLTBL_ENTRY_VM: variable name used as procname, custom mode, +* auto-selected handler (proc_dointvec for int). +*/ +static void sysctl_test_api_ctltbl_entry_vm (struct kunit *test) +{ +int foo =123 ; +struct ctl_table table =CTLTBL_ENTRY_VM (foo,0644 ); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0644 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &foo, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} + +/* +* Test CTLTBL_ENTRY_VMR: variable name used as procname, custom mode, +* auto-selected range checkint handler (proc_dointvec_minmax for int). +*/ +static void sysctl_test_api_ctltbl_entry_vmr (struct kunit *test) +{ +int foo =123 ; +struct ctl_table table =CTLTBL_ENTRY_VMR (foo,0644 ,SYSCTL_ZERO , +SYSCTL_ONE_HUNDRED ); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0644 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &foo, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec_minmax, + table.proc_handler); +} + +/* +* Test CTLTBL_ENTRY_VN: custom procname, mode 0444, +* auto-selected handler (proc_dointvec for int). +*/ +static void sysctl_test_api_ctltbl_entry_vn (struct kunit *test) +{ +int data =0 ; +struct ctl_table table =CTLTBL_ENTRY_VN (data,"foo" ); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0444 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &data, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} + +/* +* Test CTLTBL_ENTRY_VNM: custom procname and mode, +* auto-selected handler (proc_dointvec for int). +*/ +static void sysctl_test_api_ctltbl_entry_vnm (struct kunit *test) +{ +int data =0 ; +struct ctl_table table =CTLTBL_ENTRY_VNM (data,"foo" ,0644 ); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0644 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &data, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} + +/* +* Test CTLTBL_ENTRY_VNMH: custom procname, mode and explicit handler. +*/ +static void sysctl_test_api_ctltbl_entry_vnmh (struct kunit *test) +{ +int data =0 ; +struct ctl_table table =CTLTBL_ENTRY_VNMH (data,"foo" ,0644 , + proc_dointvec); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0644 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &data, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} +static struct kunit_case sysctl_test_cases[] = {KUNIT_CASE (sysctl_test_api_dointvec_null_tbl_data),KUNIT_CASE (sysctl_test_api_dointvec_table_maxlen_unset),
@@ -378,6 +414,12 @@ static struct kunit_case sysctl_test_cases[] = {KUNIT_CASE (sysctl_test_dointvec_write_happy_single_negative),KUNIT_CASE (sysctl_test_api_dointvec_write_single_less_int_min),KUNIT_CASE (sysctl_test_api_dointvec_write_single_greater_int_max), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_v), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vm), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vmr), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vn), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vnm), + KUNIT_CASE(sysctl_test_api_ctltbl_entry_vnmh), {} };
Signature · 1 line
2.25.1
Joel Granados
maintainerRe: [RFC PATCH v4 2/2] sysctl: convert kernel/sysctl-test.c to use CTLTBL_ENTRY_XXX()
Quoted 9 lines · On Wed, Mar 18, 2026 at 01:36:15AM +0800, [email protected] wrote:
From: Wen Yang <[email protected]>
Convert all struct
ctl_tableinitializations inkernel/sysctl-test.cfrom direct field assignment to indirect initialization via theCTLTBL_ENTRY_XXX()macros introduced in the previous patch. This demonstrates the macros in real usage and validates their correctness against the existing test suite.The following macro variants are exercised:
...
Quoted 22 lines
+ * auto-selected handler (
proc_dointvecfor int).
+ */kernel/sysctl-test.c +20
-0+static void sysctl_test_api_ctltbl_entry_vnm (struct kunit *test) +{ +int data =0 ; +struct ctl_table table =CTLTBL_ENTRY_VNM (data,"foo" ,0644 ); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0644 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &data, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} + +/* +* Test CTLTBL_ENTRY_VNMH: custom procname, mode and explicit handler. +*/ +static void sysctl_test_api_ctltbl_entry_vnmh (struct kunit *test) +{ +int data =0 ; + struct ctl_table table = CTLTBL_ENTRY_VNMH(data, "foo", 0644,
kernel/sysctl-test.c static void sysctl_test_api_dointvec_write_single_greater_int_max( · line 405
Quoted 10 lines
kernel/sysctl-test.c +10
-0+ proc_dointvec); + +KUNIT_EXPECT_STREQ (test,"foo" , table.procname); +KUNIT_EXPECT_EQ (test, (umode_t )0644 , table.mode); +KUNIT_EXPECT_PTR_EQ (test, &data, table.data); +KUNIT_EXPECT_EQ (test,sizeof (int ), table.maxlen); +KUNIT_EXPECT_PTR_EQ (test, (proc_handler *)proc_dointvec, + table.proc_handler); +} +
Have you checked if this approach supports u8, bool and char (string). I see that in all your tests you use an integer as data; Does it make sense to add a u8, bool and char test case to the list?
Quoted 19 lines
static struct
kunit_casesysctl_test_cases[] = {kernel/sysctl-test.c +6
-0KUNIT_CASE (sysctl_test_api_dointvec_null_tbl_data), KUNIT_CASE(sysctl_test_api_dointvec_table_maxlen_unset),@@ -378,6 +414,12 @@ static struct kunit_case sysctl_test_cases[] = {KUNIT_CASE (sysctl_test_dointvec_write_happy_single_negative),KUNIT_CASE (sysctl_test_api_dointvec_write_single_less_int_min),KUNIT_CASE (sysctl_test_api_dointvec_write_single_greater_int_max), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_v), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vm), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vmr), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vn), +KUNIT_CASE (sysctl_test_api_ctltbl_entry_vnm), + KUNIT_CASE(sysctl_test_api_ctltbl_entry_vnmh), {} };Signature · 1 line
2.25.1
Signature · 1 line
Joel Granados
Joel Granados
maintainerHey Wen
Comments inline
Quoted 8 lines · On Wed, Mar 18, 2026 at 01:36:13AM +0800, [email protected] wrote:
From: Wen Yang <[email protected]>
The main motivation for this series is to avoid treewide patch series. Historically, changes to how struct
ctl_tableentries are initialized (e.g. removing the child field, const-qualifyingctl_table) required touching hundreds of files across all subsystems. Such series require the attention of many maintainers, sometimes need to be pulled into mainline in a special way, and create lots of unnecessary churn.
LGTM: Clear motivation.
Quoted 6 lines
By introducing a family of
CTLTBL_ENTRY_XXX()helper macros in <linux/sysctl.h>, any future structural changes to structctl_tablecan be handled in one place — the macro definition — without requiring a treewide sweep of all callers. Individual subsystem maintainers can also migrate their sysctl tables to use the macros at their own pace.
I think this paragraph is redundant; I would remove it. And just add "This will all go away with the CTLTBL_ENTRY_XXX helper macros" as the last sentence in the first paragraph.
Migration strategy
==================
You touched on this when you mentioned that the maintainers can migrate to the new macro at their pace. In my experience this will never happen if you give the responsibility to the subsys maintainers (They are busy with other matters). I think the more successful strategy is to lead the conversion from sysctl.
Quoted 33 lines
Based on discussion and suggestions from:
[1] https://sysctl-dev-rtd.readthedocs.io/en/latest/notes/ctltable_entry_macro.html#table-entry-macro
[2] https://lore.kernel.org/all/psot4oeauxi3yyj2w4ajm3tfgtcsvao4rhv5sgd5s6ymmjgojk@p3vrj3qluban/This series:
1. Introduces theCTLTBL_ENTRY_XXX()macros ininclude/linux/sysctl.h, allowing callers to initialize structctl_tableentries indirectly via the macro instead of assigning each field directly. The macros use_Generic()for automatic type detection andproc_handlerselection, provide smart defaults (auto address-of, auto maxlen via sizeof), and include compile-time validation of name, mode, and handler.
2. Convertskernel/sysctl-test.cto use the new macros as a demonstration, replacing direct structctl_tablefield assignments withCTLTBL_ENTRY_XXX()calls. Four new tests are added to cover the previously untested variants (CTLTBL_ENTRY_V, VN, VNM, VNMH), bringing the total to 16 passing tests.---
Changes in v4:
- Fix Wpointer-type-mismatch warnings detected by lkp:https://lore.kernel.org/oe-kbuild-all/[email protected]/Changes in v3:
- replace the unique macro with "capital letter approach"
- reduce the name further
https://lore.kernel.org/all/rn4rsazh7kxf5byq65vw2phyqgzvwm3scczu3l5h2r4aqit2r6@znlpb24z2zuo/Changes in v2:
- add lvalue check, handler type check, etc.
https://lore.kernel.org/all/xptwb3uwbzposd4xf7khj52ifv4tchcjdgllhv7aabi6d7wgef@2msurl564v53/
Quoted 12 lines
Wen Yang (2):
sysctl: introduceCTLTBL_ENTRY_XXX()helper macros
sysctl: convertkernel/sysctl-test.cto useCTLTBL_ENTRY_XXX()include/linux/sysctl.h | 294 +++++++++++++++++++++++++++++++++++++++++ kernel/sysctl-test.c | 240 +++++++++++++++++++-------------- kernel/sysctl.c | 2 + 3 files changed, 437 insertions(+), 99 deletions(-)Signature · 1 line
2.25.1
Best
Signature · 1 line
Joel Granados
Joel Granados
maintainerQuoted 75 lines · Joel Granados
Hey Wen
Comments inline
Quoted 8 lines · On Wed, Mar 18, 2026 at 01:36:13AM +0800, [email protected] wrote:
From: Wen Yang <[email protected]>
The main motivation for this series is to avoid treewide patch series. Historically, changes to how struct
ctl_tableentries are initialized (e.g. removing the child field, const-qualifyingctl_table) required touching hundreds of files across all subsystems. Such series require the attention of many maintainers, sometimes need to be pulled into mainline in a special way, and create lots of unnecessary churn.LGTM: Clear motivation.
Quoted 6 lines
By introducing a family of
CTLTBL_ENTRY_XXX()helper macros in <linux/sysctl.h>, any future structural changes to structctl_tablecan be handled in one place — the macro definition — without requiring a treewide sweep of all callers. Individual subsystem maintainers can also migrate their sysctl tables to use the macros at their own pace.I think this paragraph is redundant; I would remove it. And just add "This will all go away with the
CTLTBL_ENTRY_XXXhelper macros" as the last sentence in the first paragraph.Migration strategy
==================
You touched on this when you mentioned that the maintainers can migrate to the new macro at their pace. In my experience this will never happen if you give the responsibility to the subsys maintainers (They are busy with other matters). I think the more successful strategy is to lead the conversion from sysctl.Quoted 42 lines
Based on discussion and suggestions from:
[1] https://sysctl-dev-rtd.readthedocs.io/en/latest/notes/ctltable_entry_macro.html#table-entry-macro
[2] https://lore.kernel.org/all/psot4oeauxi3yyj2w4ajm3tfgtcsvao4rhv5sgd5s6ymmjgojk@p3vrj3qluban/This series:
1. Introduces theCTLTBL_ENTRY_XXX()macros ininclude/linux/sysctl.h, allowing callers to initialize structctl_tableentries indirectly via the macro instead of assigning each field directly. The macros use_Generic()for automatic type detection andproc_handlerselection, provide smart defaults (auto address-of, auto maxlen via sizeof), and include compile-time validation of name, mode, and handler.
2. Convertskernel/sysctl-test.cto use the new macros as a demonstration, replacing direct structctl_tablefield assignments withCTLTBL_ENTRY_XXX()calls. Four new tests are added to cover the previously untested variants (CTLTBL_ENTRY_V, VN, VNM, VNMH), bringing the total to 16 passing tests.---
Changes in v4:
- Fix Wpointer-type-mismatch warnings detected by lkp:https://lore.kernel.org/oe-kbuild-all/[email protected]/Changes in v3:
- replace the unique macro with "capital letter approach"
- reduce the name further
https://lore.kernel.org/all/rn4rsazh7kxf5byq65vw2phyqgzvwm3scczu3l5h2r4aqit2r6@znlpb24z2zuo/Changes in v2:
- add lvalue check, handler type check, etc.
https://lore.kernel.org/all/xptwb3uwbzposd4xf7khj52ifv4tchcjdgllhv7aabi6d7wgef@2msurl564v53/Wen Yang (2):
sysctl: introduceCTLTBL_ENTRY_XXX()helper macros
sysctl: convertkernel/sysctl-test.cto useCTLTBL_ENTRY_XXX()include/linux/sysctl.h | 294 +++++++++++++++++++++++++++++++++++++++++ kernel/sysctl-test.c | 240 +++++++++++++++++++-------------- kernel/sysctl.c | 2 + 3 files changed, 437 insertions(+), 99 deletions(-)
Quoted 9 lines
Quoted 3 lines
Signature · 1 line
2.25.1Best
Signature · 1 line
Joel Granados
I think that after you address the last round of feedback, the series will be ready for a broader audience.
For your next version I would keep it as an RFC but include a more targeted audience. Add the Kees Cook <[email protected]> to the "To:" and add [email protected] to the "Cc". This will hopefully get some feedback and we can take it from there. I can nudge the new RFC if it does not get any initial traction.
Thx again for taking this
Best
Signature · 1 line
Joel Granados
Quoted 88 lines · Joel Granados
Quoted 75 lines · Joel Granados
Hey Wen
Comments inline
Quoted 8 lines · On Wed, Mar 18, 2026 at 01:36:13AM +0800, [email protected] wrote:
From: Wen Yang <[email protected]>
The main motivation for this series is to avoid treewide patch series. Historically, changes to how struct
ctl_tableentries are initialized (e.g. removing the child field, const-qualifyingctl_table) required touching hundreds of files across all subsystems. Such series require the attention of many maintainers, sometimes need to be pulled into mainline in a special way, and create lots of unnecessary churn.LGTM: Clear motivation.
Quoted 6 lines
By introducing a family of
CTLTBL_ENTRY_XXX()helper macros in <linux/sysctl.h>, any future structural changes to structctl_tablecan be handled in one place — the macro definition — without requiring a treewide sweep of all callers. Individual subsystem maintainers can also migrate their sysctl tables to use the macros at their own pace.I think this paragraph is redundant; I would remove it. And just add "This will all go away with the
CTLTBL_ENTRY_XXXhelper macros" as the last sentence in the first paragraph.Migration strategy
==================
You touched on this when you mentioned that the maintainers can migrate to the new macro at their pace. In my experience this will never happen if you give the responsibility to the subsys maintainers (They are busy with other matters). I think the more successful strategy is to lead the conversion from sysctl.Quoted 42 lines
Based on discussion and suggestions from:
[1] https://sysctl-dev-rtd.readthedocs.io/en/latest/notes/ctltable_entry_macro.html#table-entry-macro
[2] https://lore.kernel.org/all/psot4oeauxi3yyj2w4ajm3tfgtcsvao4rhv5sgd5s6ymmjgojk@p3vrj3qluban/This series:
1. Introduces theCTLTBL_ENTRY_XXX()macros ininclude/linux/sysctl.h, allowing callers to initialize structctl_tableentries indirectly via the macro instead of assigning each field directly. The macros use_Generic()for automatic type detection andproc_handlerselection, provide smart defaults (auto address-of, auto maxlen via sizeof), and include compile-time validation of name, mode, and handler.
2. Convertskernel/sysctl-test.cto use the new macros as a demonstration, replacing direct structctl_tablefield assignments withCTLTBL_ENTRY_XXX()calls. Four new tests are added to cover the previously untested variants (CTLTBL_ENTRY_V, VN, VNM, VNMH), bringing the total to 16 passing tests.---
Changes in v4:
- Fix Wpointer-type-mismatch warnings detected by lkp:https://lore.kernel.org/oe-kbuild-all/[email protected]/Changes in v3:
- replace the unique macro with "capital letter approach"
- reduce the name further
https://lore.kernel.org/all/rn4rsazh7kxf5byq65vw2phyqgzvwm3scczu3l5h2r4aqit2r6@znlpb24z2zuo/Changes in v2:
- add lvalue check, handler type check, etc.
https://lore.kernel.org/all/xptwb3uwbzposd4xf7khj52ifv4tchcjdgllhv7aabi6d7wgef@2msurl564v53/Wen Yang (2):
sysctl: introduceCTLTBL_ENTRY_XXX()helper macros
sysctl: convertkernel/sysctl-test.cto useCTLTBL_ENTRY_XXX()include/linux/sysctl.h | 294 +++++++++++++++++++++++++++++++++++++++++ kernel/sysctl-test.c | 240 +++++++++++++++++++-------------- kernel/sysctl.c | 2 + 3 files changed, 437 insertions(+), 99 deletions(-)Quoted 9 lines
Quoted 3 lines
Signature · 1 line
2.25.1Best
Signature · 1 line
Joel Granados
Quoted 6 lines
For your next version I would keep it as an RFC but include a more targeted audience. Add the Kees Cook <[email protected]> to the "To:" and add [email protected] to the "Cc". This will hopefully get some feedback and we can take it from there. I can nudge the new RFC if it does not get any initial traction.
Thank you for your kind instruction.
We will revise it based on your suggestions and send v5 soon.
--
Best wishes,
Wen