Whamcloud - gitweb
7287e0b73d4321ab1e37294cc5a7a69102222327
[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 static int
61 proc_set_timeout(struct ctl_table *table, int write, void __user *buffer,
62                  size_t *lenp, loff_t *ppos)
63 {
64         int rc;
65
66         rc = proc_dointvec(table, write, buffer, lenp, ppos);
67         if (ldlm_timeout >= obd_timeout)
68                 ldlm_timeout = max(obd_timeout / 3, 1U);
69         return rc;
70 }
71
72 static int
73 proc_memory_alloc(struct ctl_table *table, int write, void __user *buffer,
74                   size_t *lenp, loff_t *ppos)
75 {
76         char buf[22];
77         int len;
78
79         if (!*lenp || (*ppos && !write)) {
80                 *lenp = 0;
81                 return 0;
82         }
83         if (write)
84                 return -EINVAL;
85
86         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_sum());
87         if (len > *lenp)
88                 len = *lenp;
89         buf[len] = '\0';
90         if (copy_to_user(buffer, buf, len))
91                 return -EFAULT;
92         *lenp = len;
93         *ppos += *lenp;
94         return 0;
95 }
96
97 static int
98 proc_pages_alloc(struct ctl_table *table, int write, void __user *buffer,
99                  size_t *lenp, loff_t *ppos)
100 {
101         char buf[22];
102         int len;
103
104         if (!*lenp || (*ppos && !write)) {
105                 *lenp = 0;
106                 return 0;
107         }
108         if (write)
109                 return -EINVAL;
110
111         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_sum());
112         if (len > *lenp)
113                 len = *lenp;
114         buf[len] = '\0';
115         if (copy_to_user(buffer, buf, len))
116                 return -EFAULT;
117         *lenp = len;
118         *ppos += *lenp;
119         return 0;
120 }
121
122 static int
123 proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
124              size_t *lenp, loff_t *ppos)
125 {
126         char buf[22];
127         int len;
128
129         if (!*lenp || (*ppos && !write)) {
130                 *lenp = 0;
131                 return 0;
132         }
133         if (write)
134                 return -EINVAL;
135
136         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_memory_max());
137         if (len > *lenp)
138                 len = *lenp;
139         buf[len] = '\0';
140         if (copy_to_user(buffer, buf, len))
141                 return -EFAULT;
142         *lenp = len;
143         *ppos += *lenp;
144         return 0;
145 }
146
147 static int
148 proc_pages_max(struct ctl_table *table, int write, void __user *buffer,
149                size_t *lenp, loff_t *ppos)
150 {
151         char buf[22];
152         int len;
153
154         if (!*lenp || (*ppos && !write)) {
155                 *lenp = 0;
156                 return 0;
157         }
158         if (write)
159                 return -EINVAL;
160
161         len = snprintf(buf, sizeof(buf), LPU64"\n", obd_pages_max());
162         if (len > *lenp)
163                 len = *lenp;
164         buf[len] = '\0';
165         if (copy_to_user(buffer, buf, len))
166                 return -EFAULT;
167         *lenp = len;
168         *ppos += *lenp;
169         return 0;
170 }
171
172 static int
173 proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
174                            void __user *buffer, size_t *lenp, loff_t *ppos)
175 {
176         __u64 val;
177         int rc = 0;
178
179         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
180                 *lenp = 0;
181                 return 0;
182         }
183         if (write) {
184                 rc = lprocfs_write_frac_u64_helper(buffer, *lenp, &val,
185                                                1 << (20 - PAGE_CACHE_SHIFT));
186                 obd_max_dirty_pages = (unsigned long)val;
187
188                 /* Don't allow them to let dirty pages exceed 90% of system
189                  * memory and set a hard minimum of 4MB. */
190                 if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
191                         CERROR("Refusing to set max dirty pages to %lu, which "
192                                "is more than 90%% of available RAM; setting "
193                                "to %lu\n", obd_max_dirty_pages,
194                                ((totalram_pages / 10) * 9));
195                         obd_max_dirty_pages = ((totalram_pages / 10) * 9);
196                 } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
197                         obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
198                 }
199         } else {
200                 char buf[21];
201                 int len;
202
203                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
204                                                *(unsigned long *)table->data,
205                                                1 << (20 - PAGE_CACHE_SHIFT));
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         }
213         *ppos += *lenp;
214         return rc;
215 }
216
217 #ifdef RANDOM_FAIL_ALLOC
218 int proc_alloc_fail_rate(struct ctl_table *table, int write,
219                          void __user *buffer, size_t *lenp, loff_t *ppos)
220 {
221         int rc          = 0;
222
223         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
224                 *lenp = 0;
225                 return 0;
226         }
227         if (write) {
228                 rc = lprocfs_write_frac_helper(buffer, *lenp,
229                                                (unsigned int*)table->data,
230                                                OBD_ALLOC_FAIL_MULT);
231         } else {
232                 char buf[21];
233                 int  len;
234
235                 len = lprocfs_read_frac_helper(buf, 21,
236                                                *(unsigned int*)table->data,
237                                                OBD_ALLOC_FAIL_MULT);
238                 if (len > *lenp)
239                         len = *lenp;
240                 buf[len] = '\0';
241                 if (copy_to_user(buffer, buf, len))
242                         return -EFAULT;
243                 *lenp = len;
244         }
245         *ppos += *lenp;
246         return rc;
247 }
248 #endif
249
250 #ifdef CONFIG_SYSCTL
251 static struct ctl_table obd_table[] = {
252         {
253                 INIT_CTL_NAME
254                 .procname       = "timeout",
255                 .data           = &obd_timeout,
256                 .maxlen         = sizeof(int),
257                 .mode           = 0644,
258                 .proc_handler   = &proc_set_timeout
259         },
260         {
261                 INIT_CTL_NAME
262                 .procname       = "debug_peer_on_timeout",
263                 .data           = &obd_debug_peer_on_timeout,
264                 .maxlen         = sizeof(int),
265                 .mode           = 0644,
266                 .proc_handler   = &proc_dointvec
267         },
268         {
269                 INIT_CTL_NAME
270                 .procname       = "dump_on_timeout",
271                 .data           = &obd_dump_on_timeout,
272                 .maxlen         = sizeof(int),
273                 .mode           = 0644,
274                 .proc_handler   = &proc_dointvec
275         },
276         {
277                 INIT_CTL_NAME
278                 .procname       = "dump_on_eviction",
279                 .data           = &obd_dump_on_eviction,
280                 .maxlen         = sizeof(int),
281                 .mode           = 0644,
282                 .proc_handler   = &proc_dointvec
283         },
284         {
285                 INIT_CTL_NAME
286                 .procname       = "memused",
287                 .data           = NULL,
288                 .maxlen         = 0,
289                 .mode           = 0444,
290                 .proc_handler   = &proc_memory_alloc
291         },
292         {
293                 INIT_CTL_NAME
294                 .procname       = "pagesused",
295                 .data           = NULL,
296                 .maxlen         = 0,
297                 .mode           = 0444,
298                 .proc_handler   = &proc_pages_alloc
299         },
300         {
301                 INIT_CTL_NAME
302                 .procname       = "memused_max",
303                 .data           = NULL,
304                 .maxlen         = 0,
305                 .mode           = 0444,
306                 .proc_handler   = &proc_mem_max
307         },
308         {
309                 INIT_CTL_NAME
310                 .procname       = "pagesused_max",
311                 .data           = NULL,
312                 .maxlen         = 0,
313                 .mode           = 0444,
314                 .proc_handler   = &proc_pages_max
315         },
316         {
317                 INIT_CTL_NAME
318                 .procname       = "ldlm_timeout",
319                 .data           = &ldlm_timeout,
320                 .maxlen         = sizeof(int),
321                 .mode           = 0644,
322                 .proc_handler   = &proc_set_timeout
323         },
324 #ifdef RANDOM_FAIL_ALLOC
325         {
326                 INIT_CTL_NAME
327                 .procname       = "alloc_fail_rate",
328                 .data           = &obd_alloc_fail_rate,
329                 .maxlen         = sizeof(int),
330                 .mode           = 0644,
331                 .proc_handler   = &proc_alloc_fail_rate
332         },
333 #endif
334         {
335                 INIT_CTL_NAME
336                 .procname       = "max_dirty_mb",
337                 .data           = &obd_max_dirty_pages,
338                 .maxlen         = sizeof(unsigned long),
339                 .mode           = 0644,
340                 .proc_handler   = &proc_max_dirty_pages_in_mb
341         },
342         {
343                 INIT_CTL_NAME
344                 .procname       = "bulk_timeout",
345                 .data           = &bulk_timeout,
346                 .maxlen         = sizeof(int),
347                 .mode           = 0644,
348                 .proc_handler   = &proc_dointvec
349         },
350         {
351                 INIT_CTL_NAME
352                 .procname       = "at_min",
353                 .data           = &at_min,
354                 .maxlen         = sizeof(int),
355                 .mode           = 0644,
356                 .proc_handler   = &proc_dointvec
357         },
358         {
359                 INIT_CTL_NAME
360                 .procname       = "at_max",
361                 .data           = &at_max,
362                 .maxlen         = sizeof(int),
363                 .mode           = 0644,
364                 .proc_handler   = &proc_dointvec
365         },
366         {
367                 INIT_CTL_NAME
368                 .procname       = "at_extra",
369                 .data           = &at_extra,
370                 .maxlen         = sizeof(int),
371                 .mode           = 0644,
372                 .proc_handler   = &proc_dointvec
373         },
374         {
375                 INIT_CTL_NAME
376                 .procname       = "at_early_margin",
377                 .data           = &at_early_margin,
378                 .maxlen         = sizeof(int),
379                 .mode           = 0644,
380                 .proc_handler   = &proc_dointvec
381         },
382         {
383                 INIT_CTL_NAME
384                 .procname       = "at_history",
385                 .data           = &at_history,
386                 .maxlen         = sizeof(int),
387                 .mode           = 0644,
388                 .proc_handler   = &proc_dointvec
389         },
390         { 0 }
391 };
392
393 static struct ctl_table parent_table[] = {
394         {
395                 INIT_CTL_NAME
396                 .procname       = "lustre",
397                 .data           = NULL,
398                 .maxlen         = 0,
399                 .mode           = 0555,
400                 .child          = obd_table
401         },
402         { 0 }
403 };
404 #endif
405
406 void obd_sysctl_init (void)
407 {
408 #ifdef CONFIG_SYSCTL
409         if ( !obd_table_header )
410                 obd_table_header = register_sysctl_table(parent_table);
411 #endif
412 }
413
414 void obd_sysctl_clean (void)
415 {
416 #ifdef CONFIG_SYSCTL
417         if ( obd_table_header )
418                 unregister_sysctl_table(obd_table_header);
419         obd_table_header = NULL;
420 #endif
421 }