Whamcloud - gitweb
LU-224 Move fail_loc handling from lustre to libcfs
[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_TIMEOUT = 3,        /* RPC timeout before recovery/intr */
67         OBD_DUMP_ON_TIMEOUT,    /* dump kernel debug log upon eviction */
68         OBD_MEMUSED,            /* bytes currently OBD_ALLOCated */
69         OBD_PAGESUSED,          /* pages currently OBD_PAGE_ALLOCated */
70         OBD_MAXMEMUSED,         /* maximum bytes OBD_ALLOCated concurrently */
71         OBD_MAXPAGESUSED,       /* maximum pages OBD_PAGE_ALLOCated concurrently */
72         OBD_SYNCFILTER,         /* XXX temporary, as we play with sync osts.. */
73         OBD_LDLM_TIMEOUT,       /* LDLM timeout for ASTs before client eviction */
74         OBD_DUMP_ON_EVICTION,   /* dump kernel debug log upon eviction */
75         OBD_DEBUG_PEER_ON_TIMEOUT, /* dump peer debug when RPC times out */
76         OBD_ALLOC_FAIL_RATE,    /* memory allocation random failure rate */
77         OBD_MAX_DIRTY_PAGES,    /* maximum dirty pages */
78         OBD_AT_MIN,             /* Adaptive timeouts params */
79         OBD_AT_MAX,
80         OBD_AT_EXTRA,
81         OBD_AT_EARLY_MARGIN,
82         OBD_AT_HISTORY,
83 };
84
85 #else
86
87 #define OBD_SYSCTL              CTL_UNNUMBERED
88
89 #define OBD_FAIL_LOC            CTL_UNNUMBERED
90 #define OBD_FAIL_VAL            CTL_UNNUMBERED
91 #define OBD_TIMEOUT             CTL_UNNUMBERED
92 #define OBD_DUMP_ON_TIMEOUT     CTL_UNNUMBERED
93 #define OBD_MEMUSED             CTL_UNNUMBERED
94 #define OBD_PAGESUSED           CTL_UNNUMBERED
95 #define OBD_MAXMEMUSED          CTL_UNNUMBERED
96 #define OBD_MAXPAGESUSED        CTL_UNNUMBERED
97 #define OBD_SYNCFILTER          CTL_UNNUMBERED
98 #define OBD_LDLM_TIMEOUT        CTL_UNNUMBERED
99 #define OBD_DUMP_ON_EVICTION    CTL_UNNUMBERED
100 #define OBD_DEBUG_PEER_ON_TIMEOUT CTL_UNNUMBERED
101 #define OBD_ALLOC_FAIL_RATE     CTL_UNNUMBERED
102 #define OBD_MAX_DIRTY_PAGES     CTL_UNNUMBERED
103 #define OBD_AT_MIN              CTL_UNNUMBERED
104 #define OBD_AT_MAX              CTL_UNNUMBERED
105 #define OBD_AT_EXTRA            CTL_UNNUMBERED
106 #define OBD_AT_EARLY_MARGIN     CTL_UNNUMBERED
107 #define OBD_AT_HISTORY          CTL_UNNUMBERED
108
109 #endif
110
111 int LL_PROC_PROTO(proc_set_timeout)
112 {
113         int rc;
114
115         rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
116         if (ldlm_timeout >= obd_timeout)
117                 ldlm_timeout = max(obd_timeout / 3, 1U);
118         return rc;
119 }
120
121 int LL_PROC_PROTO(proc_memory_alloc)
122 {
123         char buf[22];
124         int len;
125         DECLARE_LL_PROC_PPOS_DECL;
126
127         if (!*lenp || (*ppos && !write)) {
128                 *lenp = 0;
129                 return 0;
130         }
131         if (write)
132                 return -EINVAL;
133
134         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_sum());
135         if (len > *lenp)
136                 len = *lenp;
137         buf[len] = '\0';
138         if (cfs_copy_to_user(buffer, buf, len))
139                 return -EFAULT;
140         *lenp = len;
141         *ppos += *lenp;
142         return 0;
143 }
144
145 int LL_PROC_PROTO(proc_pages_alloc)
146 {
147         char buf[22];
148         int len;
149         DECLARE_LL_PROC_PPOS_DECL;
150
151         if (!*lenp || (*ppos && !write)) {
152                 *lenp = 0;
153                 return 0;
154         }
155         if (write)
156                 return -EINVAL;
157
158         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_sum());
159         if (len > *lenp)
160                 len = *lenp;
161         buf[len] = '\0';
162         if (cfs_copy_to_user(buffer, buf, len))
163                 return -EFAULT;
164         *lenp = len;
165         *ppos += *lenp;
166         return 0;
167 }
168
169 int LL_PROC_PROTO(proc_mem_max)
170 {
171         char buf[22];
172         int len;
173         DECLARE_LL_PROC_PPOS_DECL;
174
175         if (!*lenp || (*ppos && !write)) {
176                 *lenp = 0;
177                 return 0;
178         }
179         if (write)
180                 return -EINVAL;
181
182         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_max());
183         if (len > *lenp)
184                 len = *lenp;
185         buf[len] = '\0';
186         if (cfs_copy_to_user(buffer, buf, len))
187                 return -EFAULT;
188         *lenp = len;
189         *ppos += *lenp;
190         return 0;
191 }
192
193 int LL_PROC_PROTO(proc_pages_max)
194 {
195         char buf[22];
196         int len;
197         DECLARE_LL_PROC_PPOS_DECL;
198
199         if (!*lenp || (*ppos && !write)) {
200                 *lenp = 0;
201                 return 0;
202         }
203         if (write)
204                 return -EINVAL;
205
206         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_max());
207         if (len > *lenp)
208                 len = *lenp;
209         buf[len] = '\0';
210         if (cfs_copy_to_user(buffer, buf, len))
211                 return -EFAULT;
212         *lenp = len;
213         *ppos += *lenp;
214         return 0;
215 }
216
217 int LL_PROC_PROTO(proc_max_dirty_pages_in_mb)
218 {
219         int rc = 0;
220         DECLARE_LL_PROC_PPOS_DECL;
221
222         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
223                 *lenp = 0;
224                 return 0;
225         }
226         if (write) {
227                 rc = lprocfs_write_frac_helper(buffer, *lenp,
228                                                (unsigned int*)table->data,
229                                                1 << (20 - CFS_PAGE_SHIFT));
230                 /* Don't allow them to let dirty pages exceed 90% of system
231                  * memory and set a hard minimum of 4MB. */
232                 if (obd_max_dirty_pages > ((cfs_num_physpages / 10) * 9)) {
233                         CERROR("Refusing to set max dirty pages to %u, which "
234                                "is more than 90%% of available RAM; setting "
235                                "to %lu\n", obd_max_dirty_pages,
236                                ((cfs_num_physpages / 10) * 9));
237                         obd_max_dirty_pages = ((cfs_num_physpages / 10) * 9);
238                 } else if (obd_max_dirty_pages < 4 << (20 - CFS_PAGE_SHIFT)) {
239                         obd_max_dirty_pages = 4 << (20 - CFS_PAGE_SHIFT);
240                 }
241         } else {
242                 char buf[21];
243                 int len;
244
245                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
246                                                *(unsigned int*)table->data,
247                                                1 << (20 - CFS_PAGE_SHIFT));
248                 if (len > *lenp)
249                         len = *lenp;
250                 buf[len] = '\0';
251                 if (cfs_copy_to_user(buffer, buf, len))
252                         return -EFAULT;
253                 *lenp = len;
254         }
255         *ppos += *lenp;
256         return rc;
257 }
258
259 #ifdef RANDOM_FAIL_ALLOC
260 int LL_PROC_PROTO(proc_alloc_fail_rate)
261 {
262         int rc          = 0;
263         DECLARE_LL_PROC_PPOS_DECL;
264
265         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
266                 *lenp = 0;
267                 return 0;
268         }
269         if (write) {
270                 rc = lprocfs_write_frac_helper(buffer, *lenp,
271                                                (unsigned int*)table->data,
272                                                OBD_ALLOC_FAIL_MULT);
273         } else {
274                 char buf[21];
275                 int  len;
276
277                 len = lprocfs_read_frac_helper(buf, 21,
278                                                *(unsigned int*)table->data,
279                                                OBD_ALLOC_FAIL_MULT);
280                 if (len > *lenp)
281                         len = *lenp;
282                 buf[len] = '\0';
283                 if (cfs_copy_to_user(buffer, buf, len))
284                         return -EFAULT;
285                 *lenp = len;
286         }
287         *ppos += *lenp;
288         return rc;
289 }
290 #endif
291
292 int LL_PROC_PROTO(proc_at_min)
293 {
294         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
295 }
296 int LL_PROC_PROTO(proc_at_max)
297 {
298         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
299 }
300 int LL_PROC_PROTO(proc_at_extra)
301 {
302         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
303 }
304 int LL_PROC_PROTO(proc_at_early_margin)
305 {
306         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
307 }
308 int LL_PROC_PROTO(proc_at_history)
309 {
310         return ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
311 }
312
313 #ifdef CONFIG_SYSCTL
314 static cfs_sysctl_table_t obd_table[] = {
315         {
316                 .ctl_name = OBD_TIMEOUT,
317                 .procname = "timeout",
318                 .data     = &obd_timeout,
319                 .maxlen   = sizeof(int),
320                 .mode     = 0644,
321                 .proc_handler = &proc_set_timeout
322         },
323         {
324                 .ctl_name = OBD_DEBUG_PEER_ON_TIMEOUT,
325                 .procname = "debug_peer_on_timeout",
326                 .data     = &obd_debug_peer_on_timeout,
327                 .maxlen   = sizeof(int),
328                 .mode     = 0644,
329                 .proc_handler = &proc_dointvec
330         },
331         {
332                 .ctl_name = OBD_DUMP_ON_TIMEOUT,
333                 .procname = "dump_on_timeout",
334                 .data     = &obd_dump_on_timeout,
335                 .maxlen   = sizeof(int),
336                 .mode     = 0644,
337                 .proc_handler = &proc_dointvec
338         },
339         {
340                 .ctl_name = OBD_DUMP_ON_EVICTION,
341                 .procname = "dump_on_eviction",
342                 .data     = &obd_dump_on_eviction,
343                 .maxlen   = sizeof(int),
344                 .mode     = 0644,
345                 .proc_handler = &proc_dointvec
346         },
347         {
348                 .ctl_name = OBD_MEMUSED,
349                 .procname = "memused",
350                 .data     = NULL,
351                 .maxlen   = 0,
352                 .mode     = 0444,
353                 .proc_handler = &proc_memory_alloc
354         },
355         {
356                 .ctl_name = OBD_PAGESUSED,
357                 .procname = "pagesused",
358                 .data     = NULL,
359                 .maxlen   = 0,
360                 .mode     = 0444,
361                 .proc_handler = &proc_pages_alloc
362         },
363         {
364                 .ctl_name = OBD_MAXMEMUSED,
365                 .procname = "memused_max",
366                 .data     = NULL,
367                 .maxlen   = 0,
368                 .mode     = 0444,
369                 .proc_handler = &proc_mem_max
370         },
371         {
372                 .ctl_name = OBD_MAXPAGESUSED,
373                 .procname = "pagesused_max",
374                 .data     = NULL,
375                 .maxlen   = 0,
376                 .mode     = 0444,
377                 .proc_handler = &proc_pages_max
378         },
379         {
380                 .ctl_name = OBD_LDLM_TIMEOUT,
381                 .procname = "ldlm_timeout",
382                 .data     = &ldlm_timeout,
383                 .maxlen   = sizeof(int),
384                 .mode     = 0644,
385                 .proc_handler = &proc_set_timeout
386         },
387 #ifdef RANDOM_FAIL_ALLOC
388         {
389                 .ctl_name = OBD_ALLOC_FAIL_RATE,
390                 .procname = "alloc_fail_rate",
391                 .data     = &obd_alloc_fail_rate,
392                 .maxlen   = sizeof(int),
393                 .mode     = 0644,
394                 .proc_handler = &proc_alloc_fail_rate
395         },
396 #endif
397         {
398                 .ctl_name = OBD_MAX_DIRTY_PAGES,
399                 .procname = "max_dirty_mb",
400                 .data     = &obd_max_dirty_pages,
401                 .maxlen   = sizeof(int),
402                 .mode     = 0644,
403                 .proc_handler = &proc_max_dirty_pages_in_mb
404         },
405         {
406                 .ctl_name = OBD_AT_MIN,
407                 .procname = "at_min",
408                 .data     = &at_min,
409                 .maxlen   = sizeof(int),
410                 .mode     = 0644,
411                 .proc_handler = &proc_at_min
412         },
413         {
414                 .ctl_name = OBD_AT_MAX,
415                 .procname = "at_max",
416                 .data     = &at_max,
417                 .maxlen   = sizeof(int),
418                 .mode     = 0644,
419                 .proc_handler = &proc_at_max
420         },
421         {
422                 .ctl_name = OBD_AT_EXTRA,
423                 .procname = "at_extra",
424                 .data     = &at_extra,
425                 .maxlen   = sizeof(int),
426                 .mode     = 0644,
427                 .proc_handler = &proc_at_extra
428         },
429         {
430                 .ctl_name = OBD_AT_EARLY_MARGIN,
431                 .procname = "at_early_margin",
432                 .data     = &at_early_margin,
433                 .maxlen   = sizeof(int),
434                 .mode     = 0644,
435                 .proc_handler = &proc_at_early_margin
436         },
437         {
438                 .ctl_name = OBD_AT_HISTORY,
439                 .procname = "at_history",
440                 .data     = &at_history,
441                 .maxlen   = sizeof(int),
442                 .mode     = 0644,
443                 .proc_handler = &proc_at_history
444         },
445         { 0 }
446 };
447
448 static cfs_sysctl_table_t parent_table[] = {
449         {
450                 .ctl_name = OBD_SYSCTL,
451                 .procname = "lustre",
452                 .data     = NULL,
453                 .maxlen   = 0,
454                 .mode     = 0555,
455                 .child    = obd_table
456         },
457         {0}
458 };
459 #endif
460
461 void obd_sysctl_init (void)
462 {
463 #ifdef CONFIG_SYSCTL
464         if ( !obd_table_header )
465                 obd_table_header = cfs_register_sysctl_table(parent_table, 0);
466 #endif
467 }
468
469 void obd_sysctl_clean (void)
470 {
471 #ifdef CONFIG_SYSCTL
472         if ( obd_table_header )
473                 cfs_unregister_sysctl_table(obd_table_header);
474         obd_table_header = NULL;
475 #endif
476 }