xref: /linux/net/sunrpc/sysctl.c (revision 14b42963f64b98ab61fa9723c03d71aa5ef4f862)
1 /*
2  * linux/net/sunrpc/sysctl.c
3  *
4  * Sysctl interface to sunrpc module.
5  *
6  * I would prefer to register the sunrpc table below sys/net, but that's
7  * impossible at the moment.
8  */
9 
10 #include <linux/types.h>
11 #include <linux/linkage.h>
12 #include <linux/ctype.h>
13 #include <linux/fs.h>
14 #include <linux/sysctl.h>
15 #include <linux/module.h>
16 
17 #include <asm/uaccess.h>
18 #include <linux/sunrpc/types.h>
19 #include <linux/sunrpc/sched.h>
20 #include <linux/sunrpc/stats.h>
21 #include <linux/sunrpc/xprt.h>
22 
23 /*
24  * Declare the debug flags here
25  */
26 unsigned int	rpc_debug;
27 unsigned int	nfs_debug;
28 unsigned int	nfsd_debug;
29 unsigned int	nlm_debug;
30 
31 #ifdef RPC_DEBUG
32 
33 static struct ctl_table_header *sunrpc_table_header;
34 static ctl_table		sunrpc_table[];
35 
36 void
37 rpc_register_sysctl(void)
38 {
39 	if (!sunrpc_table_header) {
40 		sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
41 #ifdef CONFIG_PROC_FS
42 		if (sunrpc_table[0].de)
43 			sunrpc_table[0].de->owner = THIS_MODULE;
44 #endif
45 	}
46 
47 }
48 
49 void
50 rpc_unregister_sysctl(void)
51 {
52 	if (sunrpc_table_header) {
53 		unregister_sysctl_table(sunrpc_table_header);
54 		sunrpc_table_header = NULL;
55 	}
56 }
57 
58 static int
59 proc_dodebug(ctl_table *table, int write, struct file *file,
60 				void __user *buffer, size_t *lenp, loff_t *ppos)
61 {
62 	char		tmpbuf[20], c, *s;
63 	char __user *p;
64 	unsigned int	value;
65 	size_t		left, len;
66 
67 	if ((*ppos && !write) || !*lenp) {
68 		*lenp = 0;
69 		return 0;
70 	}
71 
72 	left = *lenp;
73 
74 	if (write) {
75 		if (!access_ok(VERIFY_READ, buffer, left))
76 			return -EFAULT;
77 		p = buffer;
78 		while (left && __get_user(c, p) >= 0 && isspace(c))
79 			left--, p++;
80 		if (!left)
81 			goto done;
82 
83 		if (left > sizeof(tmpbuf) - 1)
84 			return -EINVAL;
85 		if (copy_from_user(tmpbuf, p, left))
86 			return -EFAULT;
87 		tmpbuf[left] = '\0';
88 
89 		for (s = tmpbuf, value = 0; '0' <= *s && *s <= '9'; s++, left--)
90 			value = 10 * value + (*s - '0');
91 		if (*s && !isspace(*s))
92 			return -EINVAL;
93 		while (left && isspace(*s))
94 			left--, s++;
95 		*(unsigned int *) table->data = value;
96 		/* Display the RPC tasks on writing to rpc_debug */
97 		if (table->ctl_name == CTL_RPCDEBUG) {
98 			rpc_show_tasks();
99 		}
100 	} else {
101 		if (!access_ok(VERIFY_WRITE, buffer, left))
102 			return -EFAULT;
103 		len = sprintf(tmpbuf, "%d", *(unsigned int *) table->data);
104 		if (len > left)
105 			len = left;
106 		if (__copy_to_user(buffer, tmpbuf, len))
107 			return -EFAULT;
108 		if ((left -= len) > 0) {
109 			if (put_user('\n', (char __user *)buffer + len))
110 				return -EFAULT;
111 			left--;
112 		}
113 	}
114 
115 done:
116 	*lenp -= left;
117 	*ppos += *lenp;
118 	return 0;
119 }
120 
121 
122 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
123 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
124 static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
125 static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
126 
127 static ctl_table debug_table[] = {
128 	{
129 		.ctl_name	= CTL_RPCDEBUG,
130 		.procname	= "rpc_debug",
131 		.data		= &rpc_debug,
132 		.maxlen		= sizeof(int),
133 		.mode		= 0644,
134 		.proc_handler	= &proc_dodebug
135 	},
136 	{
137 		.ctl_name	= CTL_NFSDEBUG,
138 		.procname	= "nfs_debug",
139 		.data		= &nfs_debug,
140 		.maxlen		= sizeof(int),
141 		.mode		= 0644,
142 		.proc_handler	= &proc_dodebug
143 	},
144 	{
145 		.ctl_name	= CTL_NFSDDEBUG,
146 		.procname	= "nfsd_debug",
147 		.data		= &nfsd_debug,
148 		.maxlen		= sizeof(int),
149 		.mode		= 0644,
150 		.proc_handler	= &proc_dodebug
151 	},
152 	{
153 		.ctl_name	= CTL_NLMDEBUG,
154 		.procname	= "nlm_debug",
155 		.data		= &nlm_debug,
156 		.maxlen		= sizeof(int),
157 		.mode		= 0644,
158 		.proc_handler	= &proc_dodebug
159 	},
160 	{
161 		.ctl_name	= CTL_SLOTTABLE_UDP,
162 		.procname	= "udp_slot_table_entries",
163 		.data		= &xprt_udp_slot_table_entries,
164 		.maxlen		= sizeof(unsigned int),
165 		.mode		= 0644,
166 		.proc_handler	= &proc_dointvec_minmax,
167 		.strategy	= &sysctl_intvec,
168 		.extra1		= &min_slot_table_size,
169 		.extra2		= &max_slot_table_size
170 	},
171 	{
172 		.ctl_name	= CTL_SLOTTABLE_TCP,
173 		.procname	= "tcp_slot_table_entries",
174 		.data		= &xprt_tcp_slot_table_entries,
175 		.maxlen		= sizeof(unsigned int),
176 		.mode		= 0644,
177 		.proc_handler	= &proc_dointvec_minmax,
178 		.strategy	= &sysctl_intvec,
179 		.extra1		= &min_slot_table_size,
180 		.extra2		= &max_slot_table_size
181 	},
182 	{
183 		.ctl_name	= CTL_MIN_RESVPORT,
184 		.procname	= "min_resvport",
185 		.data		= &xprt_min_resvport,
186 		.maxlen		= sizeof(unsigned int),
187 		.mode		= 0644,
188 		.proc_handler	= &proc_dointvec_minmax,
189 		.strategy	= &sysctl_intvec,
190 		.extra1		= &xprt_min_resvport_limit,
191 		.extra2		= &xprt_max_resvport_limit
192 	},
193 	{
194 		.ctl_name	= CTL_MAX_RESVPORT,
195 		.procname	= "max_resvport",
196 		.data		= &xprt_max_resvport,
197 		.maxlen		= sizeof(unsigned int),
198 		.mode		= 0644,
199 		.proc_handler	= &proc_dointvec_minmax,
200 		.strategy	= &sysctl_intvec,
201 		.extra1		= &xprt_min_resvport_limit,
202 		.extra2		= &xprt_max_resvport_limit
203 	},
204 	{ .ctl_name = 0 }
205 };
206 
207 static ctl_table sunrpc_table[] = {
208 	{
209 		.ctl_name	= CTL_SUNRPC,
210 		.procname	= "sunrpc",
211 		.mode		= 0555,
212 		.child		= debug_table
213 	},
214 	{ .ctl_name = 0 }
215 };
216 
217 #endif
218