Whamcloud - gitweb
LU-2800 autoconf: clean up sysctl table handling
[fs/lustre-release.git] / lustre / obdclass / linux / linux-sysctl.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #include <linux/module.h>
38 #include <linux/sysctl.h>
39 #include <linux/sched.h>
40 #include <linux/mm.h>
41 #include <linux/sysctl.h>
42 #include <linux/version.h>
43 #include <linux/proc_fs.h>
44 #include <linux/slab.h>
45 #include <linux/stat.h>
46 #include <linux/ctype.h>
47 #include <asm/bitops.h>
48 #include <asm/uaccess.h>
49 #include <linux/utsname.h>
50
51 #define DEBUG_SUBSYSTEM S_CLASS
52
53 #include <obd_support.h>
54 #include <lprocfs_status.h>
55
56 #ifdef CONFIG_SYSCTL
57 struct ctl_table_header *obd_table_header = NULL;
58 #endif
59
60 int LL_PROC_PROTO(proc_set_timeout)
61 {
62         int rc;
63
64         rc = proc_dointvec(table, write, buffer, lenp, ppos);
65         if (ldlm_timeout >= obd_timeout)
66                 ldlm_timeout = max(obd_timeout / 3, 1U);
67         return rc;
68 }
69
70 int LL_PROC_PROTO(proc_memory_alloc)
71 {
72         char buf[22];
73         int len;
74
75         if (!*lenp || (*ppos && !write)) {
76                 *lenp = 0;
77                 return 0;
78         }
79         if (write)
80                 return -EINVAL;
81
82         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_sum());
83         if (len > *lenp)
84                 len = *lenp;
85         buf[len] = '\0';
86         if (copy_to_user(buffer, buf, len))
87                 return -EFAULT;
88         *lenp = len;
89         *ppos += *lenp;
90         return 0;
91 }
92
93 int LL_PROC_PROTO(proc_pages_alloc)
94 {
95         char buf[22];
96         int len;
97
98         if (!*lenp || (*ppos && !write)) {
99                 *lenp = 0;
100                 return 0;
101         }
102         if (write)
103                 return -EINVAL;
104
105         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_sum());
106         if (len > *lenp)
107                 len = *lenp;
108         buf[len] = '\0';
109         if (copy_to_user(buffer, buf, len))
110                 return -EFAULT;
111         *lenp = len;
112         *ppos += *lenp;
113         return 0;
114 }
115
116 int LL_PROC_PROTO(proc_mem_max)
117 {
118         char buf[22];
119         int len;
120
121         if (!*lenp || (*ppos && !write)) {
122                 *lenp = 0;
123                 return 0;
124         }
125         if (write)
126                 return -EINVAL;
127
128         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_max());
129         if (len > *lenp)
130                 len = *lenp;
131         buf[len] = '\0';
132         if (copy_to_user(buffer, buf, len))
133                 return -EFAULT;
134         *lenp = len;
135         *ppos += *lenp;
136         return 0;
137 }
138
139 int LL_PROC_PROTO(proc_pages_max)
140 {
141         char buf[22];
142         int len;
143
144         if (!*lenp || (*ppos && !write)) {
145                 *lenp = 0;
146                 return 0;
147         }
148         if (write)
149                 return -EINVAL;
150
151         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_max());
152         if (len > *lenp)
153                 len = *lenp;
154         buf[len] = '\0';
155         if (copy_to_user(buffer, buf, len))
156                 return -EFAULT;
157         *lenp = len;
158         *ppos += *lenp;
159         return 0;
160 }
161
162 int LL_PROC_PROTO(proc_max_dirty_pages_in_mb)
163 {
164         int rc = 0;
165
166         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
167                 *lenp = 0;
168                 return 0;
169         }
170         if (write) {
171                 rc = lprocfs_write_frac_helper(buffer, *lenp,
172                                                (unsigned int *)table->data,
173                                                1 << (20 - PAGE_CACHE_SHIFT));
174                 /* Don't allow them to let dirty pages exceed 90% of system
175                  * memory and set a hard minimum of 4MB. */
176                 if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
177                         CERROR("Refusing to set max dirty pages to %u, which "
178                                "is more than 90%% of available RAM; setting "
179                                "to %lu\n", obd_max_dirty_pages,
180                                ((totalram_pages / 10) * 9));
181                         obd_max_dirty_pages = ((totalram_pages / 10) * 9);
182                 } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
183                         obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
184                 }
185         } else {
186                 char buf[21];
187                 int len;
188
189                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
190                                                *(unsigned int *)table->data,
191                                                1 << (20 - PAGE_CACHE_SHIFT));
192                 if (len > *lenp)
193                         len = *lenp;
194                 buf[len] = '\0';
195                 if (copy_to_user(buffer, buf, len))
196                         return -EFAULT;
197                 *lenp = len;
198         }
199         *ppos += *lenp;
200         return rc;
201 }
202
203 #ifdef RANDOM_FAIL_ALLOC
204 int proc_alloc_fail_rate(struct ctl_table *table, int write,
205                          void __user *buffer, size_t *lenp, loff_t *ppos)
206 {
207         int rc          = 0;
208
209         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
210                 *lenp = 0;
211                 return 0;
212         }
213         if (write) {
214                 rc = lprocfs_write_frac_helper(buffer, *lenp,
215                                                (unsigned int*)table->data,
216                                                OBD_ALLOC_FAIL_MULT);
217         } else {
218                 char buf[21];
219                 int  len;
220
221                 len = lprocfs_read_frac_helper(buf, 21,
222                                                *(unsigned int*)table->data,
223                                                OBD_ALLOC_FAIL_MULT);
224                 if (len > *lenp)
225                         len = *lenp;
226                 buf[len] = '\0';
227                 if (copy_to_user(buffer, buf, len))
228                         return -EFAULT;
229                 *lenp = len;
230         }
231         *ppos += *lenp;
232         return rc;
233 }
234 #endif
235
236 int LL_PROC_PROTO(proc_at_min)
237 {
238         return proc_dointvec(table, write, buffer, lenp, ppos);
239 }
240 int LL_PROC_PROTO(proc_at_max)
241 {
242         return proc_dointvec(table, write, buffer, lenp, ppos);
243 }
244 int LL_PROC_PROTO(proc_at_extra)
245 {
246         return proc_dointvec(table, write, buffer, lenp, ppos);
247 }
248 int LL_PROC_PROTO(proc_at_early_margin)
249 {
250         return proc_dointvec(table, write, buffer, lenp, ppos);
251 }
252 int LL_PROC_PROTO(proc_at_history)
253 {
254         return proc_dointvec(table, write, buffer, lenp, ppos);
255 }
256
257 #ifdef CONFIG_SYSCTL
258 static struct ctl_table obd_table[] = {
259         {
260                 INIT_CTL_NAME
261                 .procname       = "timeout",
262                 .data           = &obd_timeout,
263                 .maxlen         = sizeof(int),
264                 .mode           = 0644,
265                 .proc_handler   = &proc_set_timeout
266         },
267         {
268                 INIT_CTL_NAME
269                 .procname       = "debug_peer_on_timeout",
270                 .data           = &obd_debug_peer_on_timeout,
271                 .maxlen         = sizeof(int),
272                 .mode           = 0644,
273                 .proc_handler   = &proc_dointvec
274         },
275         {
276                 INIT_CTL_NAME
277                 .procname       = "dump_on_timeout",
278                 .data           = &obd_dump_on_timeout,
279                 .maxlen         = sizeof(int),
280                 .mode           = 0644,
281                 .proc_handler   = &proc_dointvec
282         },
283         {
284                 INIT_CTL_NAME
285                 .procname       = "dump_on_eviction",
286                 .data           = &obd_dump_on_eviction,
287                 .maxlen         = sizeof(int),
288                 .mode           = 0644,
289                 .proc_handler   = &proc_dointvec
290         },
291         {
292                 INIT_CTL_NAME
293                 .procname       = "memused",
294                 .data           = NULL,
295                 .maxlen         = 0,
296                 .mode           = 0444,
297                 .proc_handler   = &proc_memory_alloc
298         },
299         {
300                 INIT_CTL_NAME
301                 .procname       = "pagesused",
302                 .data           = NULL,
303                 .maxlen         = 0,
304                 .mode           = 0444,
305                 .proc_handler   = &proc_pages_alloc
306         },
307         {
308                 INIT_CTL_NAME
309                 .procname       = "memused_max",
310                 .data           = NULL,
311                 .maxlen         = 0,
312                 .mode           = 0444,
313                 .proc_handler   = &proc_mem_max
314         },
315         {
316                 INIT_CTL_NAME
317                 .procname       = "pagesused_max",
318                 .data           = NULL,
319                 .maxlen         = 0,
320                 .mode           = 0444,
321                 .proc_handler   = &proc_pages_max
322         },
323         {
324                 INIT_CTL_NAME
325                 .procname       = "ldlm_timeout",
326                 .data           = &ldlm_timeout,
327                 .maxlen         = sizeof(int),
328                 .mode           = 0644,
329                 .proc_handler   = &proc_set_timeout
330         },
331 #ifdef RANDOM_FAIL_ALLOC
332         {
333                 INIT_CTL_NAME
334                 .procname       = "alloc_fail_rate",
335                 .data           = &obd_alloc_fail_rate,
336                 .maxlen         = sizeof(int),
337                 .mode           = 0644,
338                 .proc_handler   = &proc_alloc_fail_rate
339         },
340 #endif
341         {
342                 INIT_CTL_NAME
343                 .procname       = "max_dirty_mb",
344                 .data           = &obd_max_dirty_pages,
345                 .maxlen         = sizeof(int),
346                 .mode           = 0644,
347                 .proc_handler   = &proc_max_dirty_pages_in_mb
348         },
349         {
350                 INIT_CTL_NAME
351                 .procname       = "at_min",
352                 .data           = &at_min,
353                 .maxlen         = sizeof(int),
354                 .mode           = 0644,
355                 .proc_handler   = &proc_at_min
356         },
357         {
358                 INIT_CTL_NAME
359                 .procname       = "at_max",
360                 .data           = &at_max,
361                 .maxlen         = sizeof(int),
362                 .mode           = 0644,
363                 .proc_handler   = &proc_at_max
364         },
365         {
366                 INIT_CTL_NAME
367                 .procname       = "at_extra",
368                 .data           = &at_extra,
369                 .maxlen         = sizeof(int),
370                 .mode           = 0644,
371                 .proc_handler   = &proc_at_extra
372         },
373         {
374                 INIT_CTL_NAME
375                 .procname       = "at_early_margin",
376                 .data           = &at_early_margin,
377                 .maxlen         = sizeof(int),
378                 .mode           = 0644,
379                 .proc_handler   = &proc_at_early_margin
380         },
381         {
382                 INIT_CTL_NAME
383                 .procname       = "at_history",
384                 .data           = &at_history,
385                 .maxlen         = sizeof(int),
386                 .mode           = 0644,
387                 .proc_handler   = &proc_at_history
388         },
389         { 0 }
390 };
391
392 static struct ctl_table parent_table[] = {
393         {
394                 INIT_CTL_NAME
395                 .procname       = "lustre",
396                 .data           = NULL,
397                 .maxlen         = 0,
398                 .mode           = 0555,
399                 .child          = obd_table
400         },
401         { 0 }
402 };
403 #endif
404
405 void obd_sysctl_init (void)
406 {
407 #ifdef CONFIG_SYSCTL
408         if ( !obd_table_header )
409                 obd_table_header = register_sysctl_table(parent_table);
410 #endif
411 }
412
413 void obd_sysctl_clean (void)
414 {
415 #ifdef CONFIG_SYSCTL
416         if ( obd_table_header )
417                 unregister_sysctl_table(obd_table_header);
418         obd_table_header = NULL;
419 #endif
420 }