1 /*
2  * Copyright (c) 2001-2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include <linux/sysctl.h>
20 #include <linux/proc_fs.h>
21 #include "xfs_error.h"
22 
23 static struct ctl_table_header *xfs_table_header;
24 
25 #ifdef CONFIG_PROC_FS
26 STATIC int
xfs_stats_clear_proc_handler(ctl_table * ctl,int write,void __user * buffer,size_t * lenp,loff_t * ppos)27 xfs_stats_clear_proc_handler(
28 	ctl_table	*ctl,
29 	int		write,
30 	void		__user *buffer,
31 	size_t		*lenp,
32 	loff_t		*ppos)
33 {
34 	int		c, ret, *valp = ctl->data;
35 	__uint32_t	vn_active;
36 
37 	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
38 
39 	if (!ret && write && *valp) {
40 		xfs_notice(NULL, "Clearing xfsstats");
41 		for_each_possible_cpu(c) {
42 			preempt_disable();
43 			/* save vn_active, it's a universal truth! */
44 			vn_active = per_cpu(xfsstats, c).vn_active;
45 			memset(&per_cpu(xfsstats, c), 0,
46 			       sizeof(struct xfsstats));
47 			per_cpu(xfsstats, c).vn_active = vn_active;
48 			preempt_enable();
49 		}
50 		xfs_stats_clear = 0;
51 	}
52 
53 	return ret;
54 }
55 
56 STATIC int
xfs_panic_mask_proc_handler(ctl_table * ctl,int write,void __user * buffer,size_t * lenp,loff_t * ppos)57 xfs_panic_mask_proc_handler(
58 	ctl_table	*ctl,
59 	int		write,
60 	void		__user *buffer,
61 	size_t		*lenp,
62 	loff_t		*ppos)
63 {
64 	int		ret, *valp = ctl->data;
65 
66 	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
67 	if (!ret && write) {
68 		xfs_panic_mask = *valp;
69 #ifdef DEBUG
70 		xfs_panic_mask |= (XFS_PTAG_SHUTDOWN_CORRUPT | XFS_PTAG_LOGRES);
71 #endif
72 	}
73 	return ret;
74 }
75 #endif /* CONFIG_PROC_FS */
76 
77 static ctl_table xfs_table[] = {
78 	{
79 		.procname	= "irix_sgid_inherit",
80 		.data		= &xfs_params.sgid_inherit.val,
81 		.maxlen		= sizeof(int),
82 		.mode		= 0644,
83 		.proc_handler	= proc_dointvec_minmax,
84 		.extra1		= &xfs_params.sgid_inherit.min,
85 		.extra2		= &xfs_params.sgid_inherit.max
86 	},
87 	{
88 		.procname	= "irix_symlink_mode",
89 		.data		= &xfs_params.symlink_mode.val,
90 		.maxlen		= sizeof(int),
91 		.mode		= 0644,
92 		.proc_handler	= proc_dointvec_minmax,
93 		.extra1		= &xfs_params.symlink_mode.min,
94 		.extra2		= &xfs_params.symlink_mode.max
95 	},
96 	{
97 		.procname	= "panic_mask",
98 		.data		= &xfs_params.panic_mask.val,
99 		.maxlen		= sizeof(int),
100 		.mode		= 0644,
101 		.proc_handler	= xfs_panic_mask_proc_handler,
102 		.extra1		= &xfs_params.panic_mask.min,
103 		.extra2		= &xfs_params.panic_mask.max
104 	},
105 
106 	{
107 		.procname	= "error_level",
108 		.data		= &xfs_params.error_level.val,
109 		.maxlen		= sizeof(int),
110 		.mode		= 0644,
111 		.proc_handler	= proc_dointvec_minmax,
112 		.extra1		= &xfs_params.error_level.min,
113 		.extra2		= &xfs_params.error_level.max
114 	},
115 	{
116 		.procname	= "xfssyncd_centisecs",
117 		.data		= &xfs_params.syncd_timer.val,
118 		.maxlen		= sizeof(int),
119 		.mode		= 0644,
120 		.proc_handler	= proc_dointvec_minmax,
121 		.extra1		= &xfs_params.syncd_timer.min,
122 		.extra2		= &xfs_params.syncd_timer.max
123 	},
124 	{
125 		.procname	= "inherit_sync",
126 		.data		= &xfs_params.inherit_sync.val,
127 		.maxlen		= sizeof(int),
128 		.mode		= 0644,
129 		.proc_handler	= proc_dointvec_minmax,
130 		.extra1		= &xfs_params.inherit_sync.min,
131 		.extra2		= &xfs_params.inherit_sync.max
132 	},
133 	{
134 		.procname	= "inherit_nodump",
135 		.data		= &xfs_params.inherit_nodump.val,
136 		.maxlen		= sizeof(int),
137 		.mode		= 0644,
138 		.proc_handler	= proc_dointvec_minmax,
139 		.extra1		= &xfs_params.inherit_nodump.min,
140 		.extra2		= &xfs_params.inherit_nodump.max
141 	},
142 	{
143 		.procname	= "inherit_noatime",
144 		.data		= &xfs_params.inherit_noatim.val,
145 		.maxlen		= sizeof(int),
146 		.mode		= 0644,
147 		.proc_handler	= proc_dointvec_minmax,
148 		.extra1		= &xfs_params.inherit_noatim.min,
149 		.extra2		= &xfs_params.inherit_noatim.max
150 	},
151 	{
152 		.procname	= "xfsbufd_centisecs",
153 		.data		= &xfs_params.xfs_buf_timer.val,
154 		.maxlen		= sizeof(int),
155 		.mode		= 0644,
156 		.proc_handler	= proc_dointvec_minmax,
157 		.extra1		= &xfs_params.xfs_buf_timer.min,
158 		.extra2		= &xfs_params.xfs_buf_timer.max
159 	},
160 	{
161 		.procname	= "age_buffer_centisecs",
162 		.data		= &xfs_params.xfs_buf_age.val,
163 		.maxlen		= sizeof(int),
164 		.mode		= 0644,
165 		.proc_handler	= proc_dointvec_minmax,
166 		.extra1		= &xfs_params.xfs_buf_age.min,
167 		.extra2		= &xfs_params.xfs_buf_age.max
168 	},
169 	{
170 		.procname	= "inherit_nosymlinks",
171 		.data		= &xfs_params.inherit_nosym.val,
172 		.maxlen		= sizeof(int),
173 		.mode		= 0644,
174 		.proc_handler	= proc_dointvec_minmax,
175 		.extra1		= &xfs_params.inherit_nosym.min,
176 		.extra2		= &xfs_params.inherit_nosym.max
177 	},
178 	{
179 		.procname	= "rotorstep",
180 		.data		= &xfs_params.rotorstep.val,
181 		.maxlen		= sizeof(int),
182 		.mode		= 0644,
183 		.proc_handler	= proc_dointvec_minmax,
184 		.extra1		= &xfs_params.rotorstep.min,
185 		.extra2		= &xfs_params.rotorstep.max
186 	},
187 	{
188 		.procname	= "inherit_nodefrag",
189 		.data		= &xfs_params.inherit_nodfrg.val,
190 		.maxlen		= sizeof(int),
191 		.mode		= 0644,
192 		.proc_handler	= proc_dointvec_minmax,
193 		.extra1		= &xfs_params.inherit_nodfrg.min,
194 		.extra2		= &xfs_params.inherit_nodfrg.max
195 	},
196 	{
197 		.procname	= "filestream_centisecs",
198 		.data		= &xfs_params.fstrm_timer.val,
199 		.maxlen		= sizeof(int),
200 		.mode		= 0644,
201 		.proc_handler	= proc_dointvec_minmax,
202 		.extra1		= &xfs_params.fstrm_timer.min,
203 		.extra2		= &xfs_params.fstrm_timer.max,
204 	},
205 	/* please keep this the last entry */
206 #ifdef CONFIG_PROC_FS
207 	{
208 		.procname	= "stats_clear",
209 		.data		= &xfs_params.stats_clear.val,
210 		.maxlen		= sizeof(int),
211 		.mode		= 0644,
212 		.proc_handler	= xfs_stats_clear_proc_handler,
213 		.extra1		= &xfs_params.stats_clear.min,
214 		.extra2		= &xfs_params.stats_clear.max
215 	},
216 #endif /* CONFIG_PROC_FS */
217 
218 	{}
219 };
220 
221 static ctl_table xfs_dir_table[] = {
222 	{
223 		.procname	= "xfs",
224 		.mode		= 0555,
225 		.child		= xfs_table
226 	},
227 	{}
228 };
229 
230 static ctl_table xfs_root_table[] = {
231 	{
232 		.procname	= "fs",
233 		.mode		= 0555,
234 		.child		= xfs_dir_table
235 	},
236 	{}
237 };
238 
239 int
xfs_sysctl_register(void)240 xfs_sysctl_register(void)
241 {
242 	xfs_table_header = register_sysctl_table(xfs_root_table);
243 	if (!xfs_table_header)
244 		return -ENOMEM;
245 	return 0;
246 }
247 
248 void
xfs_sysctl_unregister(void)249 xfs_sysctl_unregister(void)
250 {
251 	unregister_sysctl_table(xfs_table_header);
252 }
253