Whamcloud - gitweb
dc3b1fbca6f5af419ab71b4df6e7fb62a21f5224
[fs/lustre-release.git] / lustre / obdclass / linux / linux-sysctl.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
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/autoconf.h>
39 #include <linux/sysctl.h>
40 #include <linux/sched.h>
41 #include <linux/mm.h>
42 #include <linux/sysctl.h>
43 #include <linux/version.h>
44 #include <linux/proc_fs.h>
45 #include <linux/slab.h>
46 #include <linux/stat.h>
47 #include <linux/ctype.h>
48 #include <asm/bitops.h>
49 #include <asm/uaccess.h>
50 #include <linux/utsname.h>
51
52 #define DEBUG_SUBSYSTEM S_CLASS
53
54 #include <obd_support.h>
55 #include <lprocfs_status.h>
56
57 #ifdef CONFIG_SYSCTL
58 cfs_sysctl_table_header_t *obd_table_header = NULL;
59 #endif
60
61 #ifndef HAVE_SYSCTL_UNNUMBERED
62
63 #define OBD_SYSCTL 300
64
65 enum {
66         OBD_FAIL_LOC = 1,       /* control test failures instrumentation */
67         OBD_FAIL_VAL,           /* userdata for fail loc */
68         OBD_TIMEOUT,            /* RPC timeout before recovery/intr */
69         OBD_DUMP_ON_TIMEOUT,    /* dump kernel debug log upon eviction */
70         OBD_MEMUSED,            /* bytes currently OBD_ALLOCated */
71         OBD_PAGESUSED,          /* pages currently OBD_PAGE_ALLOCated */
72         OBD_MAXMEMUSED,         /* maximum bytes OBD_ALLOCated concurrently */
73         OBD_MAXPAGESUSED,       /* maximum pages OBD_PAGE_ALLOCated concurrently */
74         OBD_SYNCFILTER,         /* XXX temporary, as we play with sync osts.. */
75         OBD_LDLM_TIMEOUT,       /* LDLM timeout for ASTs before client eviction */
76         OBD_DUMP_ON_EVICTION,   /* dump kernel debug log upon eviction */
77         OBD_DEBUG_PEER_ON_TIMEOUT, /* dump peer debug when RPC times out */
78         OBD_ALLOC_FAIL_RATE,    /* memory allocation random failure rate */
79         OBD_MAX_DIRTY_PAGES,    /* maximum dirty pages */
80         OBD_AT_MIN,             /* Adaptive timeouts params */
81         OBD_AT_MAX,
82         OBD_AT_EXTRA,
83         OBD_AT_EARLY_MARGIN,
84         OBD_AT_HISTORY,
85 };
86
87 #else
88
89 #define OBD_SYSCTL              CTL_UNNUMBERED
90
91 #define OBD_FAIL_LOC            CTL_UNNUMBERED
92 #define OBD_FAIL_VAL            CTL_UNNUMBERED
93 #define OBD_TIMEOUT             CTL_UNNUMBERED
94 #define OBD_DUMP_ON_TIMEOUT     CTL_UNNUMBERED
95 #define OBD_MEMUSED             CTL_UNNUMBERED
96 #define OBD_PAGESUSED           CTL_UNNUMBERED
97 #define OBD_MAXMEMUSED          CTL_UNNUMBERED
98 #define OBD_MAXPAGESUSED        CTL_UNNUMBERED
99 #define OBD_SYNCFILTER          CTL_UNNUMBERED
100 #define OBD_LDLM_TIMEOUT        CTL_UNNUMBERED
101 #define OBD_DUMP_ON_EVICTION    CTL_UNNUMBERED
102 #define OBD_DEBUG_PEER_ON_TIMEOUT CTL_UNNUMBERED
103 #define OBD_ALLOC_FAIL_RATE     CTL_UNNUMBERED
104 #define OBD_MAX_DIRTY_PAGES     CTL_UNNUMBERED
105 #define OBD_AT_MIN              CTL_UNNUMBERED
106 #define OBD_AT_MAX              CTL_UNNUMBERED
107 #define OBD_AT_EXTRA            CTL_UNNUMBERED
108 #define OBD_AT_EARLY_MARGIN     CTL_UNNUMBERED
109 #define OBD_AT_HISTORY          CTL_UNNUMBERED
110
111 #endif
112
113
114 int LL_PROC_PROTO(proc_fail_loc)
115 {
116         int rc;
117         long old_fail_loc = obd_fail_loc;
118
119         rc = ll_proc_dolongvec(table, write, filp, buffer, lenp, ppos);
120         if (old_fail_loc != obd_fail_loc)
121                 cfs_waitq_signal(&obd_race_waitq);
122         return rc;
123 }
124
125 int LL_PROC_PROTO(proc_set_timeout)
126 {
127         int rc;
128
129         rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
130         if (ldlm_timeout >= obd_timeout)
131                 ldlm_timeout = max(obd_timeout / 3, 1U);
132         return rc;
133 }
134
135 int LL_PROC_PROTO(proc_memory_alloc)
136 {
137         char buf[22];
138         int len;
139         DECLARE_LL_PROC_PPOS_DECL;
140
141         if (!*lenp || (*ppos && !write)) {
142                 *lenp = 0;
143                 return 0;
144         }
145         if (write)
146                 return -EINVAL;
147
148         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_sum());
149         if (len > *lenp)
150                 len = *lenp;
151         buf[len] = '\0';
152         if (cfs_copy_to_user(buffer, buf, len))
153                 return -EFAULT;
154         *lenp = len;
155         *ppos += *lenp;
156         return 0;
157 }
158
159 int LL_PROC_PROTO(proc_pages_alloc)
160 {
161         char buf[22];
162         int len;
163         DECLARE_LL_PROC_PPOS_DECL;
164
165         if (!*lenp || (*ppos && !write)) {
166                 *lenp = 0;
167                 return 0;
168         }
169         if (write)
170                 return -EINVAL;
171
172         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_sum());
173         if (len > *lenp)
174                 len = *lenp;
175         buf[len] = '\0';
176         if (cfs_copy_to_user(buffer, buf, len))
177                 return -EFAULT;
178         *lenp = len;
179         *ppos += *lenp;
180         return 0;
181 }
182
183 int LL_PROC_PROTO(proc_mem_max)
184 {
185         char buf[22];
186         int len;
187         DECLARE_LL_PROC_PPOS_DECL;
188
189         if (!*lenp || (*ppos && !write)) {
190                 *lenp = 0;
191                 return 0;
192         }
193         if (write)
194                 return -EINVAL;
195
196         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_max());
197         if (len > *lenp)
198                 len = *lenp;
199         buf[len] = '\0';
200         if (cfs_copy_to_user(buffer, buf, len))
201                 return -EFAULT;
202         *lenp = len;
203         *ppos += *lenp;
204         return 0;
205 }
206
207 int LL_PROC_PROTO(proc_pages_max)
208 {
209         char buf[22];
210         int len;
211         DECLARE_LL_PROC_PPOS_DECL;
212
213         if (!*lenp || (*ppos && !write)) {
214                 *lenp = 0;
215                 return 0;
216         }
217         if (write)
218                 return -EINVAL;
219
220         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_max());
221         if (len > *lenp)
222                 len = *lenp;
223         buf[len] = '\0';
224         if (cfs_copy_to_user(buffer, buf, len))
225                 return -EFAULT;
226         *lenp = len;
227         *ppos += *lenp;
228         return 0;
229 }
230
231 int LL_PROC_PROTO(proc_max_dirty_pages_in_mb)
232 {
233         int rc = 0;
234         DECLARE_LL_PROC_PPOS_DECL;
235
236         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
237                 *lenp = 0;
238                 return 0;
239         }
240         if (write) {
241                 rc = lprocfs_write_frac_helper(buffer, *lenp,
242                                                (unsigned int*)table->data,
243                                                1 << (20 - CFS_PAGE_SHIFT));
244                 /* Don't allow them to let dirty pages exceed 90% of system
245                  * memory and set a hard minimum of 4MB. */
246                 if (obd_max_dirty_pages > ((cfs_num_physpages / 10) * 9)) {
247                         CERROR("Refusing to set max dirty pages to %u, which "
248                                "is more than 90%% of available RAM; setting "
249                                "to %lu\n", obd_max_dirty_pages,
250                                ((cfs_num_physpages / 10) * 9));
251                         obd_max_dirty_pages = ((cfs_num_physpages / 10) * 9);
252                 } else if (obd_max_dirty_pages < 4 << (20 - CFS_PAGE_SHIFT)) {
253                         obd_max_dirty_pages = 4 << (20 - CFS_PAGE_SHIFT);
254                 }
255         } else {
256                 char buf[21];
257                 int len;
258
259                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
260                                                *(unsigned int*)table->data,
261                                                1 << (20 - CFS_PAGE_SHIFT));
262                 if (len > *lenp)
263                         len = *lenp;
264                 buf[len] = '\0';
265                 if (cfs_copy_to_user(buffer, buf, len))
266                         return -EFAULT;
267                 *lenp = len;
268         }
269         *ppos += *lenp;
270         return rc;
271 }
272
273 #ifdef RANDOM_FAIL_ALLOC
274 int LL_PROC_PROTO(proc_alloc_fail_rate)
275 {
276         int rc          = 0;
277         DECLARE_LL_PROC_PPOS_DECL;
278
279         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
280                 *lenp = 0;
281                 return 0;
282         }
283         if (write) {
284                 rc = lprocfs_write_frac_helper(buffer, *lenp,
285                                                (unsigned int*)table->data,
286                                                OBD_ALLOC_FAIL_MULT);
287         } else {
288                 char buf[21];
289                 int  len;
290
291                 len = lprocfs_read_frac_helper(buf, 21,
292                                                *(unsigned int*)table->data,
293                                                OBD_ALLOC_FAIL_MULT);
294                 if (len > *lenp)
295                         len = *lenp;
296                 buf[len] = '\0';
297                 if (cfs_copy_to_user(buffer, buf, len))
298                         return -EFAULT;
299                 *lenp = len;
300         }
301         *ppos += *lenp;
302         return rc;
303 }
304 #endif
305
306 int LL_PROC_PROTO(proc_at_min)
307 {
308         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
309 }
310 int LL_PROC_PROTO(proc_at_max)
311 {
312         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
313 }
314 int LL_PROC_PROTO(proc_at_extra)
315 {
316         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
317 }
318 int LL_PROC_PROTO(proc_at_early_margin)
319 {
320         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
321 }
322 int LL_PROC_PROTO(proc_at_history)
323 {
324         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
325 }
326
327 #ifdef CONFIG_SYSCTL
328 static cfs_sysctl_table_t obd_table[] = {
329         {
330                 .ctl_name = OBD_FAIL_LOC,
331                 .procname = "fail_loc",
332                 .data     = &obd_fail_loc,
333                 .maxlen   = sizeof(obd_fail_loc),
334                 .mode     = 0644,
335                 .proc_handler = &proc_fail_loc
336         },
337         {
338                 .ctl_name = OBD_FAIL_VAL,
339                 .procname = "fail_val",
340                 .data     = &obd_fail_val,
341                 .maxlen   = sizeof(int),
342                 .mode     = 0644,
343                 .proc_handler = &proc_dointvec
344         },
345         {
346                 .ctl_name = OBD_TIMEOUT,
347                 .procname = "timeout",
348                 .data     = &obd_timeout,
349                 .maxlen   = sizeof(int),
350                 .mode     = 0644,
351                 .proc_handler = &proc_set_timeout
352         },
353         {
354                 .ctl_name = OBD_DEBUG_PEER_ON_TIMEOUT,
355                 .procname = "debug_peer_on_timeout",
356                 .data     = &obd_debug_peer_on_timeout,
357                 .maxlen   = sizeof(int),
358                 .mode     = 0644,
359                 .proc_handler = &proc_dointvec
360         },
361         {
362                 .ctl_name = OBD_DUMP_ON_TIMEOUT,
363                 .procname = "dump_on_timeout",
364                 .data     = &obd_dump_on_timeout,
365                 .maxlen   = sizeof(int),
366                 .mode     = 0644,
367                 .proc_handler = &proc_dointvec
368         },
369         {
370                 .ctl_name = OBD_DUMP_ON_EVICTION,
371                 .procname = "dump_on_eviction",
372                 .data     = &obd_dump_on_eviction,
373                 .maxlen   = sizeof(int),
374                 .mode     = 0644,
375                 .proc_handler = &proc_dointvec
376         },
377         {
378                 .ctl_name = OBD_MEMUSED,
379                 .procname = "memused",
380                 .data     = NULL,
381                 .maxlen   = 0,
382                 .mode     = 0444,
383                 .proc_handler = &proc_memory_alloc
384         },
385         {
386                 .ctl_name = OBD_PAGESUSED,
387                 .procname = "pagesused",
388                 .data     = NULL,
389                 .maxlen   = 0,
390                 .mode     = 0444,
391                 .proc_handler = &proc_pages_alloc
392         },
393         {
394                 .ctl_name = OBD_MAXMEMUSED,
395                 .procname = "memused_max",
396                 .data     = NULL,
397                 .maxlen   = 0,
398                 .mode     = 0444,
399                 .proc_handler = &proc_mem_max
400         },
401         {
402                 .ctl_name = OBD_MAXPAGESUSED,
403                 .procname = "pagesused_max",
404                 .data     = NULL,
405                 .maxlen   = 0,
406                 .mode     = 0444,
407                 .proc_handler = &proc_pages_max
408         },
409         {
410                 .ctl_name = OBD_LDLM_TIMEOUT,
411                 .procname = "ldlm_timeout",
412                 .data     = &ldlm_timeout,
413                 .maxlen   = sizeof(int),
414                 .mode     = 0644,
415                 .proc_handler = &proc_set_timeout
416         },
417 #ifdef RANDOM_FAIL_ALLOC
418         {
419                 .ctl_name = OBD_ALLOC_FAIL_RATE,
420                 .procname = "alloc_fail_rate",
421                 .data     = &obd_alloc_fail_rate,
422                 .maxlen   = sizeof(int),
423                 .mode     = 0644,
424                 .proc_handler = &proc_alloc_fail_rate
425         },
426 #endif
427         {
428                 .ctl_name = OBD_MAX_DIRTY_PAGES,
429                 .procname = "max_dirty_mb",
430                 .data     = &obd_max_dirty_pages,
431                 .maxlen   = sizeof(int),
432                 .mode     = 0644,
433                 .proc_handler = &proc_max_dirty_pages_in_mb
434         },
435         {
436                 .ctl_name = OBD_AT_MIN,
437                 .procname = "at_min",
438                 .data     = &at_min,
439                 .maxlen   = sizeof(int),
440                 .mode     = 0644,
441                 .proc_handler = &proc_at_min
442         },
443         {
444                 .ctl_name = OBD_AT_MAX,
445                 .procname = "at_max",
446                 .data     = &at_max,
447                 .maxlen   = sizeof(int),
448                 .mode     = 0644,
449                 .proc_handler = &proc_at_max
450         },
451         {
452                 .ctl_name = OBD_AT_EXTRA,
453                 .procname = "at_extra",
454                 .data     = &at_extra,
455                 .maxlen   = sizeof(int),
456                 .mode     = 0644,
457                 .proc_handler = &proc_at_extra
458         },
459         {
460                 .ctl_name = OBD_AT_EARLY_MARGIN,
461                 .procname = "at_early_margin",
462                 .data     = &at_early_margin,
463                 .maxlen   = sizeof(int),
464                 .mode     = 0644,
465                 .proc_handler = &proc_at_early_margin
466         },
467         {
468                 .ctl_name = OBD_AT_HISTORY,
469                 .procname = "at_history",
470                 .data     = &at_history,
471                 .maxlen   = sizeof(int),
472                 .mode     = 0644,
473                 .proc_handler = &proc_at_history
474         },
475         { 0 }
476 };
477
478 static cfs_sysctl_table_t parent_table[] = {
479         {
480                 .ctl_name = OBD_SYSCTL,
481                 .procname = "lustre",
482                 .data     = NULL,
483                 .maxlen   = 0,
484                 .mode     = 0555,
485                 .child    = obd_table
486         },
487         {0}
488 };
489 #endif
490
491 void obd_sysctl_init (void)
492 {
493 #ifdef CONFIG_SYSCTL
494         if ( !obd_table_header )
495                 obd_table_header = cfs_register_sysctl_table(parent_table, 0);
496 #endif
497 }
498
499 void obd_sysctl_clean (void)
500 {
501 #ifdef CONFIG_SYSCTL
502         if ( obd_table_header )
503                 cfs_unregister_sysctl_table(obd_table_header);
504         obd_table_header = NULL;
505 #endif
506 }