xref: /openbmc/linux/net/sunrpc/sysctl.c (revision f15cbe6f1a4b4d9df59142fc8e4abb973302cf44)
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/svc_xprt.h>
22 
23 /*
24  * Declare the debug flags here
25  */
26 unsigned int	rpc_debug;
27 EXPORT_SYMBOL_GPL(rpc_debug);
28 
29 unsigned int	nfs_debug;
30 EXPORT_SYMBOL_GPL(nfs_debug);
31 
32 unsigned int	nfsd_debug;
33 EXPORT_SYMBOL_GPL(nfsd_debug);
34 
35 unsigned int	nlm_debug;
36 EXPORT_SYMBOL_GPL(nlm_debug);
37 
38 #ifdef RPC_DEBUG
39 
40 static struct ctl_table_header *sunrpc_table_header;
41 static ctl_table		sunrpc_table[];
42 
43 void
44 rpc_register_sysctl(void)
45 {
46 	if (!sunrpc_table_header)
47 		sunrpc_table_header = register_sysctl_table(sunrpc_table);
48 }
49 
50 void
51 rpc_unregister_sysctl(void)
52 {
53 	if (sunrpc_table_header) {
54 		unregister_sysctl_table(sunrpc_table_header);
55 		sunrpc_table_header = NULL;
56 	}
57 }
58 
59 static int proc_do_xprt(ctl_table *table, int write, struct file *file,
60 			void __user *buffer, size_t *lenp, loff_t *ppos)
61 {
62 	char tmpbuf[256];
63 	int len;
64 	if ((*ppos && !write) || !*lenp) {
65 		*lenp = 0;
66 		return 0;
67 	}
68 	if (write)
69 		return -EINVAL;
70 	else {
71 		len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
72 		if (!access_ok(VERIFY_WRITE, buffer, len))
73 			return -EFAULT;
74 
75 		if (__copy_to_user(buffer, tmpbuf, len))
76 			return -EFAULT;
77 	}
78 	*lenp -= len;
79 	*ppos += len;
80 	return 0;
81 }
82 
83 static int
84 proc_dodebug(ctl_table *table, int write, struct file *file,
85 				void __user *buffer, size_t *lenp, loff_t *ppos)
86 {
87 	char		tmpbuf[20], c, *s;
88 	char __user *p;
89 	unsigned int	value;
90 	size_t		left, len;
91 
92 	if ((*ppos && !write) || !*lenp) {
93 		*lenp = 0;
94 		return 0;
95 	}
96 
97 	left = *lenp;
98 
99 	if (write) {
100 		if (!access_ok(VERIFY_READ, buffer, left))
101 			return -EFAULT;
102 		p = buffer;
103 		while (left && __get_user(c, p) >= 0 && isspace(c))
104 			left--, p++;
105 		if (!left)
106 			goto done;
107 
108 		if (left > sizeof(tmpbuf) - 1)
109 			return -EINVAL;
110 		if (copy_from_user(tmpbuf, p, left))
111 			return -EFAULT;
112 		tmpbuf[left] = '\0';
113 
114 		for (s = tmpbuf, value = 0; '0' <= *s && *s <= '9'; s++, left--)
115 			value = 10 * value + (*s - '0');
116 		if (*s && !isspace(*s))
117 			return -EINVAL;
118 		while (left && isspace(*s))
119 			left--, s++;
120 		*(unsigned int *) table->data = value;
121 		/* Display the RPC tasks on writing to rpc_debug */
122 		if (strcmp(table->procname, "rpc_debug") == 0)
123 			rpc_show_tasks();
124 	} else {
125 		if (!access_ok(VERIFY_WRITE, buffer, left))
126 			return -EFAULT;
127 		len = sprintf(tmpbuf, "%d", *(unsigned int *) table->data);
128 		if (len > left)
129 			len = left;
130 		if (__copy_to_user(buffer, tmpbuf, len))
131 			return -EFAULT;
132 		if ((left -= len) > 0) {
133 			if (put_user('\n', (char __user *)buffer + len))
134 				return -EFAULT;
135 			left--;
136 		}
137 	}
138 
139 done:
140 	*lenp -= left;
141 	*ppos += *lenp;
142 	return 0;
143 }
144 
145 
146 static ctl_table debug_table[] = {
147 	{
148 		.procname	= "rpc_debug",
149 		.data		= &rpc_debug,
150 		.maxlen		= sizeof(int),
151 		.mode		= 0644,
152 		.proc_handler	= &proc_dodebug
153 	},
154 	{
155 		.procname	= "nfs_debug",
156 		.data		= &nfs_debug,
157 		.maxlen		= sizeof(int),
158 		.mode		= 0644,
159 		.proc_handler	= &proc_dodebug
160 	},
161 	{
162 		.procname	= "nfsd_debug",
163 		.data		= &nfsd_debug,
164 		.maxlen		= sizeof(int),
165 		.mode		= 0644,
166 		.proc_handler	= &proc_dodebug
167 	},
168 	{
169 		.procname	= "nlm_debug",
170 		.data		= &nlm_debug,
171 		.maxlen		= sizeof(int),
172 		.mode		= 0644,
173 		.proc_handler	= &proc_dodebug
174 	},
175 	{
176 		.procname	= "transports",
177 		.maxlen		= 256,
178 		.mode		= 0444,
179 		.proc_handler	= &proc_do_xprt,
180 	},
181 	{ .ctl_name = 0 }
182 };
183 
184 static ctl_table sunrpc_table[] = {
185 	{
186 		.ctl_name	= CTL_SUNRPC,
187 		.procname	= "sunrpc",
188 		.mode		= 0555,
189 		.child		= debug_table
190 	},
191 	{ .ctl_name = 0 }
192 };
193 
194 #endif
195