Whamcloud - gitweb
326218f6e1b57769a12e465272c00f372112b370
[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_bulk_timeout)
237 {
238         return proc_dointvec(table, write, buffer, lenp, ppos);
239 }
240 int LL_PROC_PROTO(proc_at_min)
241 {
242         return proc_dointvec(table, write, buffer, lenp, ppos);
243 }
244 int LL_PROC_PROTO(proc_at_max)
245 {
246         return proc_dointvec(table, write, buffer, lenp, ppos);
247 }
248 int LL_PROC_PROTO(proc_at_extra)
249 {
250         return proc_dointvec(table, write, buffer, lenp, ppos);
251 }
252 int LL_PROC_PROTO(proc_at_early_margin)
253 {
254         return proc_dointvec(table, write, buffer, lenp, ppos);
255 }
256 int LL_PROC_PROTO(proc_at_history)
257 {
258         return proc_dointvec(table, write, buffer, lenp, ppos);
259 }
260
261 #ifdef CONFIG_SYSCTL
262 static struct ctl_table obd_table[] = {
263         {
264                 INIT_CTL_NAME
265                 .procname       = "timeout",
266                 .data           = &obd_timeout,
267                 .maxlen         = sizeof(int),
268                 .mode           = 0644,
269                 .proc_handler   = &proc_set_timeout
270         },
271         {
272                 INIT_CTL_NAME
273                 .procname       = "debug_peer_on_timeout",
274                 .data           = &obd_debug_peer_on_timeout,
275                 .maxlen         = sizeof(int),
276                 .mode           = 0644,
277                 .proc_handler   = &proc_dointvec
278         },
279         {
280                 INIT_CTL_NAME
281                 .procname       = "dump_on_timeout",
282                 .data           = &obd_dump_on_timeout,
283                 .maxlen         = sizeof(int),
284                 .mode           = 0644,
285                 .proc_handler   = &proc_dointvec
286         },
287         {
288                 INIT_CTL_NAME
289                 .procname       = "dump_on_eviction",
290                 .data           = &obd_dump_on_eviction,
291                 .maxlen         = sizeof(int),
292                 .mode           = 0644,
293                 .proc_handler   = &proc_dointvec
294         },
295         {
296                 INIT_CTL_NAME
297                 .procname       = "memused",
298                 .data           = NULL,
299                 .maxlen         = 0,
300                 .mode           = 0444,
301                 .proc_handler   = &proc_memory_alloc
302         },
303         {
304                 INIT_CTL_NAME
305                 .procname       = "pagesused",
306                 .data           = NULL,
307                 .maxlen         = 0,
308                 .mode           = 0444,
309                 .proc_handler   = &proc_pages_alloc
310         },
311         {
312                 INIT_CTL_NAME
313                 .procname       = "memused_max",
314                 .data           = NULL,
315                 .maxlen         = 0,
316                 .mode           = 0444,
317                 .proc_handler   = &proc_mem_max
318         },
319         {
320                 INIT_CTL_NAME
321                 .procname       = "pagesused_max",
322                 .data           = NULL,
323                 .maxlen         = 0,
324                 .mode           = 0444,
325                 .proc_handler   = &proc_pages_max
326         },
327         {
328                 INIT_CTL_NAME
329                 .procname       = "ldlm_timeout",
330                 .data           = &ldlm_timeout,
331                 .maxlen         = sizeof(int),
332                 .mode           = 0644,
333                 .proc_handler   = &proc_set_timeout
334         },
335 #ifdef RANDOM_FAIL_ALLOC
336         {
337                 INIT_CTL_NAME
338                 .procname       = "alloc_fail_rate",
339                 .data           = &obd_alloc_fail_rate,
340                 .maxlen         = sizeof(int),
341                 .mode           = 0644,
342                 .proc_handler   = &proc_alloc_fail_rate
343         },
344 #endif
345         {
346                 INIT_CTL_NAME
347                 .procname       = "max_dirty_mb",
348                 .data           = &obd_max_dirty_pages,
349                 .maxlen         = sizeof(int),
350                 .mode           = 0644,
351                 .proc_handler   = &proc_max_dirty_pages_in_mb
352         },
353         {
354                 INIT_CTL_NAME
355                 .procname       = "bulk_timeout",
356                 .data           = &bulk_timeout,
357                 .maxlen         = sizeof(int),
358                 .mode           = 0644,
359                 .proc_handler   = &proc_bulk_timeout
360         },
361         {
362                 INIT_CTL_NAME
363                 .procname       = "at_min",
364                 .data           = &at_min,
365                 .maxlen         = sizeof(int),
366                 .mode           = 0644,
367                 .proc_handler   = &proc_at_min
368         },
369         {
370                 INIT_CTL_NAME
371                 .procname       = "at_max",
372                 .data           = &at_max,
373                 .maxlen         = sizeof(int),
374                 .mode           = 0644,
375                 .proc_handler   = &proc_at_max
376         },
377         {
378                 INIT_CTL_NAME
379                 .procname       = "at_extra",
380                 .data           = &at_extra,
381                 .maxlen         = sizeof(int),
382                 .mode           = 0644,
383                 .proc_handler   = &proc_at_extra
384         },
385         {
386                 INIT_CTL_NAME
387                 .procname       = "at_early_margin",
388                 .data           = &at_early_margin,
389                 .maxlen         = sizeof(int),
390                 .mode           = 0644,
391                 .proc_handler   = &proc_at_early_margin
392         },
393         {
394                 INIT_CTL_NAME
395                 .procname       = "at_history",
396                 .data           = &at_history,
397                 .maxlen         = sizeof(int),
398                 .mode           = 0644,
399                 .proc_handler   = &proc_at_history
400         },
401         { 0 }
402 };
403
404 static struct ctl_table parent_table[] = {
405         {
406                 INIT_CTL_NAME
407                 .procname       = "lustre",
408                 .data           = NULL,
409                 .maxlen         = 0,
410                 .mode           = 0555,
411                 .child          = obd_table
412         },
413         { 0 }
414 };
415 #endif
416
417 void obd_sysctl_init (void)
418 {
419 #ifdef CONFIG_SYSCTL
420         if ( !obd_table_header )
421                 obd_table_header = register_sysctl_table(parent_table);
422 #endif
423 }
424
425 void obd_sysctl_clean (void)
426 {
427 #ifdef CONFIG_SYSCTL
428         if ( obd_table_header )
429                 unregister_sysctl_table(obd_table_header);
430         obd_table_header = NULL;
431 #endif
432 }