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