[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <8996bbfd86079cff39e1bbf7f645e4c099c5081e.1770496163.git.wen.yang@linux.dev>
Date: Sun, 8 Feb 2026 04:35:17 +0800
From: wen.yang@...ux.dev
To: Joel Granados <joel.granados@...nel.org>
Cc: linux-kernel@...r.kernel.org,
Wen Yang <wen.yang@...ux.dev>
Subject: [RFC PATCH v2 2/2] sysctl: convert kernel/sysctl-test.c to use SYSCTL_TBL_ENTRY()
From: Wen Yang <wen.yang@...ux.dev>
Convert sysctl test cases to use the new SYSCTL_TBL_ENTRY() macro,
demonstrating the macro's benefits in reducing boilerplate and
improving code readability.
This conversion shows typical usage patterns:
- Standard entries with range checking:
Before (11 lines):
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 (2 lines):
struct ctl_table table = SYSCTL_TBL_ENTRY("foo", data, 0644,
SYSCTL_ZERO, SYSCTL_ONE_HUNDRED);
- NULL data entries:
Before (11 lines with explicit .data = NULL):
struct ctl_table null_data_table = {
.procname = "foo",
.data = NULL,
.maxlen = sizeof(int),
...
};
After (3 lines using SYSCTL_NULL marker):
struct ctl_table null_data_table = SYSCTL_TBL_ENTRY("foo", SYSCTL_NULL, 0644,
proc_dointvec,
SYSCTL_ZERO, SYSCTL_ONE_HUNDRED);
- Explicit maxlen override:
SYSCTL_TBL_ENTRY("foo", SYSCTL_NULL, 0644, proc_dointvec,
SYSCTL_ZERO, SYSCTL_ONE_HUNDRED, 0);
Benefits demonstrated:
- 60% reduction in lines of code (from ~110 to ~44 lines for table definitions)
- Automatic address-of operator (&data) - macro handles it
- Automatic maxlen calculation via sizeof() when appropriate
- Improved readability - focus on important parameters
- Consistent formatting across all test cases
The macro automatically:
- Takes the address of 'data' variable
- Computes maxlen as sizeof(int)
- Selects proc_dointvec based on type (though explicitly provided here)
- Validates all parameters at compile time
No functional change - all tests continue to pass.
[17:55:08] ================ sysctl_test (10 subtests) =================
[17:55:08] [PASSED] sysctl_test_api_dointvec_null_tbl_data
[17:55:08] [PASSED] sysctl_test_api_dointvec_table_maxlen_unset
[17:55:08] [PASSED] sysctl_test_api_dointvec_table_len_is_zero
[17:55:08] [PASSED] sysctl_test_api_dointvec_table_read_but_position_set
[17:55:08] [PASSED] sysctl_test_dointvec_read_happy_single_positive
[17:55:08] [PASSED] sysctl_test_dointvec_read_happy_single_negative
[17:55:08] [PASSED] sysctl_test_dointvec_write_happy_single_positive
[17:55:08] [PASSED] sysctl_test_dointvec_write_happy_single_negative
[17:55:08] [PASSED] sysctl_test_api_dointvec_write_single_less_int_min
[17:55:08] [PASSED] sysctl_test_api_dointvec_write_single_greater_int_max
[17:55:08] =================== [PASSED] sysctl_test ===================
[17:55:08] ============================================================
[17:55:08] Testing complete. Ran 10 tests: passed: 10
Suggested-by: Joel Granados <joel.granados@...nel.org>
Signed-off-by: Wen Yang <wen.yang@...ux.dev>
---
kernel/sysctl-test.c | 139 +++++++++++++------------------------------
1 file changed, 40 insertions(+), 99 deletions(-)
diff --git a/kernel/sysctl-test.c b/kernel/sysctl-test.c
index 92f94ea28957..bacd782d8cee 100644
--- a/kernel/sysctl-test.c
+++ b/kernel/sysctl-test.c
@@ -15,20 +15,15 @@
*/
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 = SYSCTL_TBL_ENTRY("foo", SYSCTL_NULL, 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 +61,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 = SYSCTL_TBL_ENTRY("foo", \
+ data, 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 +103,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 = SYSCTL_TBL_ENTRY("foo", \
+ data, 0644, SYSCTL_ZERO, SYSCTL_ONE_HUNDRED);
void __user *buffer = (void __user *)kunit_kzalloc(test, sizeof(int),
GFP_USER);
/*
@@ -147,15 +130,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 0644, \
+ SYSCTL_ZERO, \
+ SYSCTL_ONE_HUNDRED);
void __user *buffer = (void __user *)kunit_kzalloc(test, sizeof(int),
GFP_USER);
/*
@@ -182,15 +159,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 0644, \
+ SYSCTL_ZERO, \
+ SYSCTL_ONE_HUNDRED);
size_t len = 4;
loff_t pos = 0;
char *buffer = kunit_kzalloc(test, len, GFP_USER);
@@ -213,15 +184,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 0644, \
+ SYSCTL_ZERO, \
+ SYSCTL_ONE_HUNDRED);
size_t len = 5;
loff_t pos = 0;
char *buffer = kunit_kzalloc(test, len, GFP_USER);
@@ -242,15 +207,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 0644, \
+ SYSCTL_ZERO, \
+ SYSCTL_ONE_HUNDRED);
char input[] = "9";
size_t len = sizeof(input) - 1;
loff_t pos = 0;
@@ -272,15 +231,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 0644, \
+ SYSCTL_ZERO, \
+ SYSCTL_ONE_HUNDRED);
char input[] = "-9";
size_t len = sizeof(input) - 1;
loff_t pos = 0;
@@ -304,15 +257,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 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 +289,9 @@ 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 = SYSCTL_TBL_ENTRY("foo", data, 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);
--
2.25.1
Powered by blists - more mailing lists