Whamcloud - gitweb
LU-4856 obdclass: check val in proc_max_dirty_pages_in_mb()
[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
187                 /* Don't allow them to let dirty pages exceed 90% of system
188                  * memory and set a hard minimum of 4MB. */
189                 if (val > ((totalram_pages / 10) * 9)) {
190                         CERROR("Refusing to set max dirty pages to "LPU64", "
191                                "which is more than 90%% of available RAM; "
192                                "setting to %lu\n", val,
193                                ((totalram_pages / 10) * 9));
194                         obd_max_dirty_pages = ((totalram_pages / 10) * 9);
195                 } else if (val < 4 << (20 - PAGE_CACHE_SHIFT)) {
196                         obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
197                 } else {
198                         obd_max_dirty_pages = val;
199                 }
200         } else {
201                 char buf[21];
202                 int len;
203
204                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
205                                                *(unsigned long *)table->data,
206                                                1 << (20 - PAGE_CACHE_SHIFT));
207                 if (len > *lenp)
208                         len = *lenp;
209                 buf[len] = '\0';
210                 if (copy_to_user(buffer, buf, len))
211                         return -EFAULT;
212                 *lenp = len;
213         }
214         *ppos += *lenp;
215         return rc;
216 }
217
218 #ifdef RANDOM_FAIL_ALLOC
219 int proc_alloc_fail_rate(struct ctl_table *table, int write,
220                          void __user *buffer, size_t *lenp, loff_t *ppos)
221 {
222         int rc          = 0;
223
224         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
225                 *lenp = 0;
226                 return 0;
227         }
228         if (write) {
229                 rc = lprocfs_write_frac_helper(buffer, *lenp,
230                                                (unsigned int*)table->data,
231                                                OBD_ALLOC_FAIL_MULT);
232         } else {
233                 char buf[21];
234                 int  len;
235
236                 len = lprocfs_read_frac_helper(buf, 21,
237                                                *(unsigned int*)table->data,
238                                                OBD_ALLOC_FAIL_MULT);
239                 if (len > *lenp)
240                         len = *lenp;
241                 buf[len] = '\0';
242                 if (copy_to_user(buffer, buf, len))
243                         return -EFAULT;
244                 *lenp = len;
245         }
246         *ppos += *lenp;
247         return rc;
248 }
249 #endif
250
251 #ifdef CONFIG_SYSCTL
252 static struct ctl_table obd_table[] = {
253         {
254                 INIT_CTL_NAME
255                 .procname       = "timeout",
256                 .data           = &obd_timeout,
257                 .maxlen         = sizeof(int),
258                 .mode           = 0644,
259                 .proc_handler   = &proc_set_timeout
260         },
261         {
262                 INIT_CTL_NAME
263                 .procname       = "debug_peer_on_timeout",
264                 .data           = &obd_debug_peer_on_timeout,
265                 .maxlen         = sizeof(int),
266                 .mode           = 0644,
267                 .proc_handler   = &proc_dointvec
268         },
269         {
270                 INIT_CTL_NAME
271                 .procname       = "dump_on_timeout",
272                 .data           = &obd_dump_on_timeout,
273                 .maxlen         = sizeof(int),
274                 .mode           = 0644,
275                 .proc_handler   = &proc_dointvec
276         },
277         {
278                 INIT_CTL_NAME
279                 .procname       = "dump_on_eviction",
280                 .data           = &obd_dump_on_eviction,
281                 .maxlen         = sizeof(int),
282                 .mode           = 0644,
283                 .proc_handler   = &proc_dointvec
284         },
285         {
286                 INIT_CTL_NAME
287                 .procname       = "memused",
288                 .data           = NULL,
289                 .maxlen         = 0,
290                 .mode           = 0444,
291                 .proc_handler   = &proc_memory_alloc
292         },
293         {
294                 INIT_CTL_NAME
295                 .procname       = "pagesused",
296                 .data           = NULL,
297                 .maxlen         = 0,
298                 .mode           = 0444,
299                 .proc_handler   = &proc_pages_alloc
300         },
301         {
302                 INIT_CTL_NAME
303                 .procname       = "memused_max",
304                 .data           = NULL,
305                 .maxlen         = 0,
306                 .mode           = 0444,
307                 .proc_handler   = &proc_mem_max
308         },
309         {
310                 INIT_CTL_NAME
311                 .procname       = "pagesused_max",
312                 .data           = NULL,
313                 .maxlen         = 0,
314                 .mode           = 0444,
315                 .proc_handler   = &proc_pages_max
316         },
317         {
318                 INIT_CTL_NAME
319                 .procname       = "ldlm_timeout",
320                 .data           = &ldlm_timeout,
321                 .maxlen         = sizeof(int),
322                 .mode           = 0644,
323                 .proc_handler   = &proc_set_timeout
324         },
325 #ifdef RANDOM_FAIL_ALLOC
326         {
327                 INIT_CTL_NAME
328                 .procname       = "alloc_fail_rate",
329                 .data           = &obd_alloc_fail_rate,
330                 .maxlen         = sizeof(int),
331                 .mode           = 0644,
332                 .proc_handler   = &proc_alloc_fail_rate
333         },
334 #endif
335         {
336                 INIT_CTL_NAME
337                 .procname       = "max_dirty_mb",
338                 .data           = &obd_max_dirty_pages,
339                 .maxlen         = sizeof(unsigned long),
340                 .mode           = 0644,
341                 .proc_handler   = &proc_max_dirty_pages_in_mb
342         },
343         {
344                 INIT_CTL_NAME
345                 .procname       = "bulk_timeout",
346                 .data           = &bulk_timeout,
347                 .maxlen         = sizeof(int),
348                 .mode           = 0644,
349                 .proc_handler   = &proc_dointvec
350         },
351         {
352                 INIT_CTL_NAME
353                 .procname       = "at_min",
354                 .data           = &at_min,
355                 .maxlen         = sizeof(int),
356                 .mode           = 0644,
357                 .proc_handler   = &proc_dointvec
358         },
359         {
360                 INIT_CTL_NAME
361                 .procname       = "at_max",
362                 .data           = &at_max,
363                 .maxlen         = sizeof(int),
364                 .mode           = 0644,
365                 .proc_handler   = &proc_dointvec
366         },
367         {
368                 INIT_CTL_NAME
369                 .procname       = "at_extra",
370                 .data           = &at_extra,
371                 .maxlen         = sizeof(int),
372                 .mode           = 0644,
373                 .proc_handler   = &proc_dointvec
374         },
375         {
376                 INIT_CTL_NAME
377                 .procname       = "at_early_margin",
378                 .data           = &at_early_margin,
379                 .maxlen         = sizeof(int),
380                 .mode           = 0644,
381                 .proc_handler   = &proc_dointvec
382         },
383         {
384                 INIT_CTL_NAME
385                 .procname       = "at_history",
386                 .data           = &at_history,
387                 .maxlen         = sizeof(int),
388                 .mode           = 0644,
389                 .proc_handler   = &proc_dointvec
390         },
391         { 0 }
392 };
393
394 static struct ctl_table parent_table[] = {
395         {
396                 INIT_CTL_NAME
397                 .procname       = "lustre",
398                 .data           = NULL,
399                 .maxlen         = 0,
400                 .mode           = 0555,
401                 .child          = obd_table
402         },
403         { 0 }
404 };
405 #endif
406
407 void obd_sysctl_init (void)
408 {
409 #ifdef CONFIG_SYSCTL
410         if ( !obd_table_header )
411                 obd_table_header = register_sysctl_table(parent_table);
412 #endif
413 }
414
415 void obd_sysctl_clean (void)
416 {
417 #ifdef CONFIG_SYSCTL
418         if ( obd_table_header )
419                 unregister_sysctl_table(obd_table_header);
420         obd_table_header = NULL;
421 #endif
422 }