From nobody Wed Feb 11 10:51:08 2026 Received: from out-183.mta1.migadu.com (out-183.mta1.migadu.com [95.215.58.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E1B3389DF4 for ; Tue, 13 Jan 2026 17:40:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.183 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768326061; cv=none; b=Mnj4XJlayBpHLJVJ/yUeqeJ1AXY/ssfPQf/8ehJoLZMMfvnlF06aJjy0DhpGXvSsyyMTI2A0763bGjA3PRKxtLV7ucstFjMJBjpcRkFMt2FaszQdvTLCFINkDkROh9YbgEMvHMPQ10NRu21a9/VA/rX6DQHEHnzRWQO6MftGJbE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768326061; c=relaxed/simple; bh=h+CWyFH79b+ck649UTadWNeq1frfKSYLW3i0Y1ktqcY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FYh/Nf3fgBpC1Bhc6xUFzNt1IIXOKGcsKyAFGX8p/Kj7oE65uEP7z+tnQgruMf4GMkMQWn2l/qG48I8WjdRsJX00tdvWeu+EWHdlRVGqTQuP0rrixIg/RfrLsyH080Dte3NNS7FdACApnPhx1w8THhKpc3LXGGy+WmyuGv6B8VE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=GGXAyyCj; arc=none smtp.client-ip=95.215.58.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="GGXAyyCj" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1768326057; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tGPLKt/qbYWtt+2IkGYIoT8dXR/EXHgixA9v9y5+YHU=; b=GGXAyyCj635jxIejGsiwqr/Iq71TsLfTm4/40TIeDDRHyWBgwWvYb4KJUXmIxNV4EN/jsN /REiTRenvzmP98Ld7p2on4YxXMehIp/Nyrqvl+697R8Gvzn+R55xR4vaEFlrTgOpuVzIBY 9tz5z9dljhuMfc/JS88GZ6AYIbkUFWM= From: wen.yang@linux.dev To: Joel Granados Cc: linux-kernel@vger.kernel.org, Wen Yang Subject: [RFC PATCH 1/4] sysctl: add SYSCTL_ENTRY/SYSCTL_RANGE_ENTRY helpers for ctl_table init Date: Wed, 14 Jan 2026 01:40:30 +0800 Message-Id: <09f6437ba1aeb067be4d295ec79f2d51f5355ce0.1768324215.git.wen.yang@linux.dev> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Wen Yang Introduce SYSCTL_ENTRY() and SYSCTL_RANGE_ENTRY() (built on __SYSCTL_ENTRY(= )) to consolidate common struct ctl_table initializers in one place. This is a preparatory refactor in support of future tree-wide sysctl cleanups by making the how to build a ctl_table entry logic uniform. Also add SYSCTL_NULL for explicitly passing a NULL .data pointer through the new macros, and convert a few in-tree users (kernel/sysctl.c) to validate the new helpers. No functional change intended. Selftest were also made: [19:31:40] Starting KUnit Kernel (1/1)... [19:31:40] =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Running tests with: $ .kunit/linux kunit.filter_glob=3Dsysctl_test kunit.enable=3D1 mem=3D1G co= nsole=3Dtty kunit_shutdown=3Dhalt [19:31:40] =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D sysctl_test (10= subtests) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [19:31:40] [PASSED] sysctl_test_api_dointvec_null_tbl_data [19:31:40] [PASSED] sysctl_test_api_dointvec_table_maxlen_unset [19:31:40] [PASSED] sysctl_test_api_dointvec_table_len_is_zero [19:31:40] [PASSED] sysctl_test_api_dointvec_table_read_but_position_set [19:31:40] [PASSED] sysctl_test_dointvec_read_happy_single_positive [19:31:40] [PASSED] sysctl_test_dointvec_read_happy_single_negative [19:31:40] [PASSED] sysctl_test_dointvec_write_happy_single_positive [19:31:40] [PASSED] sysctl_test_dointvec_write_happy_single_negative [19:31:40] [PASSED] sysctl_test_api_dointvec_write_single_less_int_min [19:31:40] [PASSED] sysctl_test_api_dointvec_write_single_greater_int_max [19:31:40] =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [PASSE= D] sysctl_test =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [19:31:40] =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [19:31:40] Testing complete. Ran 10 tests: passed: 10 [19:31:40] Elapsed time: 26.755s total, 0.002s configuring, 26.632s buildin= g, 0.102s running Suggested-by: Joel Granados Link: https://lore.kernel.org/all/7mevcgca7xsd5gckrap22byjinhrgqnelu4y7hzo2= r5t2cq7w4@nyaa42khwqez/#t Signed-off-by: Wen Yang --- include/linux/sysctl.h | 18 ++++++ kernel/sysctl-test.c | 131 ++++++++++------------------------------- kernel/sysctl.c | 43 ++------------ 3 files changed, 56 insertions(+), 136 deletions(-) diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 2886fbceb5d6..683422bc3e7f 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -53,6 +53,7 @@ struct ctl_dir; #define SYSCTL_MAXOLDUID ((void *)&sysctl_vals[10]) #define SYSCTL_NEG_ONE ((void *)&sysctl_vals[11]) =20 +#define SYSCTL_NULL ((void *)NULL) extern const int sysctl_vals[]; =20 #define SYSCTL_LONG_ZERO ((void *)&sysctl_long_vals[0]) @@ -175,6 +176,23 @@ struct ctl_table { void *extra2; } __randomize_layout; =20 +#define __SYSCTL_ENTRY(NAME, DATA, TYPE, MODE, HANDLER, SMIN, SMAX)\ + { \ + .procname =3D NAME, \ + .data =3D DATA, \ + .maxlen =3D sizeof(TYPE), \ + .mode =3D MODE, \ + .proc_handler =3D HANDLER, \ + .extra1 =3D SMIN, \ + .extra2 =3D SMAX, \ + } + +#define SYSCTL_ENTRY(NAME, DATA, TYPE, MODE) \ + __SYSCTL_ENTRY(NAME, DATA, TYPE, MODE, proc_do##TYPE##vec, NULL, NULL) + +#define SYSCTL_RANGE_ENTRY(NAME, DATA, TYPE, MODE, SMIN, SMAX) \ + __SYSCTL_ENTRY(NAME, DATA, TYPE, MODE, proc_do##TYPE##vec_minmax, SMIN, S= MAX) + struct ctl_node { struct rb_node node; struct ctl_table_header *header; diff --git a/kernel/sysctl-test.c b/kernel/sysctl-test.c index 92f94ea28957..7fb0e7f1e62f 100644 --- a/kernel/sysctl-test.c +++ b/kernel/sysctl-test.c @@ -15,20 +15,14 @@ */ static void sysctl_test_api_dointvec_null_tbl_data(struct kunit *test) { - struct ctl_table null_data_table =3D { - .procname =3D "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 =3D NULL, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D 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 =3D SYSCTL_RANGE_ENTRY("foo", \ + SYSCTL_NULL, int, 0644, 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(stru= ct kunit *test) static void sysctl_test_api_dointvec_table_maxlen_unset(struct kunit *test) { int data =3D 0; - struct ctl_table data_maxlen_unset_table =3D { - .procname =3D "foo", - .data =3D &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 =3D 0, - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D 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 =3D SYSCTL_RANGE_ENTRY("foo", \ + &data, int, 0644, SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); + data_maxlen_unset_table.maxlen =3D 0; void __user *buffer =3D (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 =3D 0; /* Good table. */ - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644,\ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); void __user *buffer =3D (void __user *)kunit_kzalloc(test, sizeof(int), GFP_USER); /* @@ -147,15 +129,8 @@ static void sysctl_test_api_dointvec_table_read_but_po= sition_set( { int data =3D 0; /* Good table. */ - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644,\ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); void __user *buffer =3D (void __user *)kunit_kzalloc(test, sizeof(int), GFP_USER); /* @@ -182,15 +157,8 @@ static void sysctl_test_dointvec_read_happy_single_pos= itive(struct kunit *test) { int data =3D 0; /* Good table. */ - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644, \ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); size_t len =3D 4; loff_t pos =3D 0; char *buffer =3D kunit_kzalloc(test, len, GFP_USER); @@ -213,15 +181,8 @@ static void sysctl_test_dointvec_read_happy_single_neg= ative(struct kunit *test) { int data =3D 0; /* Good table. */ - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644, \ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); size_t len =3D 5; loff_t pos =3D 0; char *buffer =3D kunit_kzalloc(test, len, GFP_USER); @@ -242,15 +203,8 @@ static void sysctl_test_dointvec_write_happy_single_po= sitive(struct kunit *test) { int data =3D 0; /* Good table. */ - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644, \ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); char input[] =3D "9"; size_t len =3D sizeof(input) - 1; loff_t pos =3D 0; @@ -272,15 +226,8 @@ static void sysctl_test_dointvec_write_happy_single_po= sitive(struct kunit *test) static void sysctl_test_dointvec_write_happy_single_negative(struct kunit = *test) { int data =3D 0; - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644, \ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); char input[] =3D "-9"; size_t len =3D sizeof(input) - 1; loff_t pos =3D 0; @@ -304,15 +251,8 @@ static void sysctl_test_api_dointvec_write_single_less= _int_min( struct kunit *test) { int data =3D 0; - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644,\ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); size_t max_len =3D 32, len =3D max_len; loff_t pos =3D 0; char *buffer =3D kunit_kzalloc(test, max_len, GFP_USER); @@ -342,15 +282,8 @@ static void sysctl_test_api_dointvec_write_single_grea= ter_int_max( struct kunit *test) { int data =3D 0; - struct ctl_table table =3D { - .procname =3D "foo", - .data =3D &data, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - .extra1 =3D SYSCTL_ZERO, - .extra2 =3D SYSCTL_ONE_HUNDRED, - }; + struct ctl_table table =3D SYSCTL_RANGE_ENTRY("foo", &data, int, 0644,\ + SYSCTL_ZERO, SYSCTL_ONE_HUNDRED); size_t max_len =3D 32, len =3D max_len; loff_t pos =3D 0; char *buffer =3D kunit_kzalloc(test, max_len, GFP_USER); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9d3a666ffde1..2e769550b268 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1373,47 +1373,16 @@ int proc_do_static_key(const struct ctl_table *tabl= e, int dir, =20 static const struct ctl_table sysctl_subsys_table[] =3D { #ifdef CONFIG_PROC_SYSCTL - { - .procname =3D "sysctl_writes_strict", - .data =3D &sysctl_writes_strict, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D SYSCTL_NEG_ONE, - .extra2 =3D SYSCTL_ONE, - }, + SYSCTL_RANGE_ENTRY("sysctl_writes_strict", &sysctl_writes_strict, int, \ + 0644, SYSCTL_NEG_ONE, SYSCTL_ONE), #endif - { - .procname =3D "ngroups_max", - .data =3D (void *)&ngroups_max, - .maxlen =3D sizeof (int), - .mode =3D 0444, - .proc_handler =3D proc_dointvec, - }, - { - .procname =3D "cap_last_cap", - .data =3D (void *)&cap_last_cap, - .maxlen =3D sizeof(int), - .mode =3D 0444, - .proc_handler =3D proc_dointvec, - }, + SYSCTL_ENTRY("ngroups_max", (void *)&ngroups_max, int, 0444), + SYSCTL_ENTRY("cap_last_cap", (void *)&cap_last_cap, int, 0444), #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW - { - .procname =3D "unaligned-trap", - .data =3D &unaligned_enabled, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - }, + SYSCTL_ENTRY("unaligned-trap", &unaligned_enabled, int, 0644), #endif #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN - { - .procname =3D "ignore-unaligned-usertrap", - .data =3D &no_unaligned_warning, - .maxlen =3D sizeof (int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec, - }, + SYSCTL_ENTRY("ignore-unaligned-usertrap", &no_unaligned_warning, int, 064= 4), #endif }; =20 --=20 2.25.1