xref: /linux/lib/test_sysctl.c (revision 7c43a657a4beadeb6d2fe1a00732261e313a807f)
19308f2f9SLuis R. Rodriguez /*
29308f2f9SLuis R. Rodriguez  * proc sysctl test driver
39308f2f9SLuis R. Rodriguez  *
49308f2f9SLuis R. Rodriguez  * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
59308f2f9SLuis R. Rodriguez  *
69308f2f9SLuis R. Rodriguez  * This program is free software; you can redistribute it and/or modify it
79308f2f9SLuis R. Rodriguez  * under the terms of the GNU General Public License as published by the Free
89308f2f9SLuis R. Rodriguez  * Software Foundation; either version 2 of the License, or at your option any
99308f2f9SLuis R. Rodriguez  * later version; or, when distributed separately from the Linux kernel or
109308f2f9SLuis R. Rodriguez  * when incorporated into other software packages, subject to the following
119308f2f9SLuis R. Rodriguez  * license:
129308f2f9SLuis R. Rodriguez  *
139308f2f9SLuis R. Rodriguez  * This program is free software; you can redistribute it and/or modify it
149308f2f9SLuis R. Rodriguez  * under the terms of copyleft-next (version 0.3.1 or later) as published
159308f2f9SLuis R. Rodriguez  * at http://copyleft-next.org/.
169308f2f9SLuis R. Rodriguez  */
179308f2f9SLuis R. Rodriguez 
189308f2f9SLuis R. Rodriguez /*
199308f2f9SLuis R. Rodriguez  * This module provides an interface to the the proc sysctl interfaces.  This
209308f2f9SLuis R. Rodriguez  * driver requires CONFIG_PROC_SYSCTL. It will not normally be loaded by the
219308f2f9SLuis R. Rodriguez  * system unless explicitly requested by name. You can also build this driver
229308f2f9SLuis R. Rodriguez  * into your kernel.
239308f2f9SLuis R. Rodriguez  */
249308f2f9SLuis R. Rodriguez 
259308f2f9SLuis R. Rodriguez #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
269308f2f9SLuis R. Rodriguez 
279308f2f9SLuis R. Rodriguez #include <linux/init.h>
289308f2f9SLuis R. Rodriguez #include <linux/list.h>
299308f2f9SLuis R. Rodriguez #include <linux/module.h>
309308f2f9SLuis R. Rodriguez #include <linux/printk.h>
319308f2f9SLuis R. Rodriguez #include <linux/fs.h>
329308f2f9SLuis R. Rodriguez #include <linux/miscdevice.h>
339308f2f9SLuis R. Rodriguez #include <linux/slab.h>
349308f2f9SLuis R. Rodriguez #include <linux/uaccess.h>
359308f2f9SLuis R. Rodriguez #include <linux/async.h>
369308f2f9SLuis R. Rodriguez #include <linux/delay.h>
379308f2f9SLuis R. Rodriguez #include <linux/vmalloc.h>
389308f2f9SLuis R. Rodriguez 
399308f2f9SLuis R. Rodriguez static int i_zero;
409308f2f9SLuis R. Rodriguez static int i_one_hundred = 100;
419308f2f9SLuis R. Rodriguez 
429308f2f9SLuis R. Rodriguez struct test_sysctl_data {
439308f2f9SLuis R. Rodriguez 	int int_0001;
44eb965edaSLuis R. Rodriguez 	int int_0002;
45*7c43a657SLuis R. Rodriguez 	int int_0003[4];
46eb965edaSLuis R. Rodriguez 
472920fad3SLuis R. Rodriguez 	unsigned int uint_0001;
482920fad3SLuis R. Rodriguez 
499308f2f9SLuis R. Rodriguez 	char string_0001[65];
509308f2f9SLuis R. Rodriguez };
519308f2f9SLuis R. Rodriguez 
529308f2f9SLuis R. Rodriguez static struct test_sysctl_data test_data = {
539308f2f9SLuis R. Rodriguez 	.int_0001 = 60,
54eb965edaSLuis R. Rodriguez 	.int_0002 = 1,
55eb965edaSLuis R. Rodriguez 
56*7c43a657SLuis R. Rodriguez 	.int_0003[0] = 0,
57*7c43a657SLuis R. Rodriguez 	.int_0003[1] = 1,
58*7c43a657SLuis R. Rodriguez 	.int_0003[2] = 2,
59*7c43a657SLuis R. Rodriguez 	.int_0003[3] = 3,
60*7c43a657SLuis R. Rodriguez 
612920fad3SLuis R. Rodriguez 	.uint_0001 = 314,
622920fad3SLuis R. Rodriguez 
639308f2f9SLuis R. Rodriguez 	.string_0001 = "(none)",
649308f2f9SLuis R. Rodriguez };
659308f2f9SLuis R. Rodriguez 
669308f2f9SLuis R. Rodriguez /* These are all under /proc/sys/debug/test_sysctl/ */
679308f2f9SLuis R. Rodriguez static struct ctl_table test_table[] = {
689308f2f9SLuis R. Rodriguez 	{
699308f2f9SLuis R. Rodriguez 		.procname	= "int_0001",
709308f2f9SLuis R. Rodriguez 		.data		= &test_data.int_0001,
719308f2f9SLuis R. Rodriguez 		.maxlen		= sizeof(int),
729308f2f9SLuis R. Rodriguez 		.mode		= 0644,
739308f2f9SLuis R. Rodriguez 		.proc_handler	= proc_dointvec_minmax,
749308f2f9SLuis R. Rodriguez 		.extra1		= &i_zero,
759308f2f9SLuis R. Rodriguez 		.extra2         = &i_one_hundred,
769308f2f9SLuis R. Rodriguez 	},
779308f2f9SLuis R. Rodriguez 	{
78eb965edaSLuis R. Rodriguez 		.procname	= "int_0002",
79eb965edaSLuis R. Rodriguez 		.data		= &test_data.int_0002,
80eb965edaSLuis R. Rodriguez 		.maxlen		= sizeof(int),
81eb965edaSLuis R. Rodriguez 		.mode		= 0644,
82eb965edaSLuis R. Rodriguez 		.proc_handler	= proc_dointvec,
83eb965edaSLuis R. Rodriguez 	},
84eb965edaSLuis R. Rodriguez 	{
85*7c43a657SLuis R. Rodriguez 		.procname	= "int_0003",
86*7c43a657SLuis R. Rodriguez 		.data		= &test_data.int_0003,
87*7c43a657SLuis R. Rodriguez 		.maxlen		= sizeof(test_data.int_0003),
88*7c43a657SLuis R. Rodriguez 		.mode		= 0644,
89*7c43a657SLuis R. Rodriguez 		.proc_handler	= proc_dointvec,
90*7c43a657SLuis R. Rodriguez 	},
91*7c43a657SLuis R. Rodriguez 	{
922920fad3SLuis R. Rodriguez 		.procname	= "uint_0001",
932920fad3SLuis R. Rodriguez 		.data		= &test_data.uint_0001,
942920fad3SLuis R. Rodriguez 		.maxlen		= sizeof(unsigned int),
952920fad3SLuis R. Rodriguez 		.mode		= 0644,
962920fad3SLuis R. Rodriguez 		.proc_handler	= proc_douintvec,
972920fad3SLuis R. Rodriguez 	},
982920fad3SLuis R. Rodriguez 	{
999308f2f9SLuis R. Rodriguez 		.procname	= "string_0001",
1009308f2f9SLuis R. Rodriguez 		.data		= &test_data.string_0001,
1019308f2f9SLuis R. Rodriguez 		.maxlen		= sizeof(test_data.string_0001),
1029308f2f9SLuis R. Rodriguez 		.mode		= 0644,
1039308f2f9SLuis R. Rodriguez 		.proc_handler	= proc_dostring,
1049308f2f9SLuis R. Rodriguez 	},
1059308f2f9SLuis R. Rodriguez 	{ }
1069308f2f9SLuis R. Rodriguez };
1079308f2f9SLuis R. Rodriguez 
1089308f2f9SLuis R. Rodriguez static struct ctl_table test_sysctl_table[] = {
1099308f2f9SLuis R. Rodriguez 	{
1109308f2f9SLuis R. Rodriguez 		.procname	= "test_sysctl",
1119308f2f9SLuis R. Rodriguez 		.maxlen		= 0,
1129308f2f9SLuis R. Rodriguez 		.mode		= 0555,
1139308f2f9SLuis R. Rodriguez 		.child		= test_table,
1149308f2f9SLuis R. Rodriguez 	},
1159308f2f9SLuis R. Rodriguez 	{ }
1169308f2f9SLuis R. Rodriguez };
1179308f2f9SLuis R. Rodriguez 
1189308f2f9SLuis R. Rodriguez static struct ctl_table test_sysctl_root_table[] = {
1199308f2f9SLuis R. Rodriguez 	{
1209308f2f9SLuis R. Rodriguez 		.procname	= "debug",
1219308f2f9SLuis R. Rodriguez 		.maxlen		= 0,
1229308f2f9SLuis R. Rodriguez 		.mode		= 0555,
1239308f2f9SLuis R. Rodriguez 		.child		= test_sysctl_table,
1249308f2f9SLuis R. Rodriguez 	},
1259308f2f9SLuis R. Rodriguez 	{ }
1269308f2f9SLuis R. Rodriguez };
1279308f2f9SLuis R. Rodriguez 
1289308f2f9SLuis R. Rodriguez static struct ctl_table_header *test_sysctl_header;
1299308f2f9SLuis R. Rodriguez 
1309308f2f9SLuis R. Rodriguez static int __init test_sysctl_init(void)
1319308f2f9SLuis R. Rodriguez {
1329308f2f9SLuis R. Rodriguez 	test_sysctl_header = register_sysctl_table(test_sysctl_root_table);
1339308f2f9SLuis R. Rodriguez 	if (!test_sysctl_header)
1349308f2f9SLuis R. Rodriguez 		return -ENOMEM;
1359308f2f9SLuis R. Rodriguez 	return 0;
1369308f2f9SLuis R. Rodriguez }
1379308f2f9SLuis R. Rodriguez late_initcall(test_sysctl_init);
1389308f2f9SLuis R. Rodriguez 
1399308f2f9SLuis R. Rodriguez static void __exit test_sysctl_exit(void)
1409308f2f9SLuis R. Rodriguez {
1419308f2f9SLuis R. Rodriguez 	if (test_sysctl_header)
1429308f2f9SLuis R. Rodriguez 		unregister_sysctl_table(test_sysctl_header);
1439308f2f9SLuis R. Rodriguez }
1449308f2f9SLuis R. Rodriguez 
1459308f2f9SLuis R. Rodriguez module_exit(test_sysctl_exit);
1469308f2f9SLuis R. Rodriguez 
1479308f2f9SLuis R. Rodriguez MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
1489308f2f9SLuis R. Rodriguez MODULE_LICENSE("GPL");
149