Merge tag 'tty-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
[cascardo/linux.git] / drivers / staging / lustre / 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/proc_fs.h>
42 #include <linux/slab.h>
43 #include <linux/stat.h>
44 #include <linux/ctype.h>
45 #include <linux/bitops.h>
46 #include <linux/uaccess.h>
47 #include <linux/utsname.h>
48
49 #define DEBUG_SUBSYSTEM S_CLASS
50
51 #include "../../include/obd_support.h"
52 #include "../../include/lprocfs_status.h"
53
54 #ifdef CONFIG_SYSCTL
55 static struct ctl_table_header *obd_table_header;
56 #endif
57
58
59 #define OBD_SYSCTL 300
60
61 enum {
62         OBD_TIMEOUT = 3,        /* RPC timeout before recovery/intr */
63         OBD_DUMP_ON_TIMEOUT,    /* dump kernel debug log upon eviction */
64         OBD_MEMUSED,        /* bytes currently OBD_ALLOCated */
65         OBD_PAGESUSED,    /* pages currently OBD_PAGE_ALLOCated */
66         OBD_MAXMEMUSED,  /* maximum bytes OBD_ALLOCated concurrently */
67         OBD_MAXPAGESUSED,       /* maximum pages OBD_PAGE_ALLOCated concurrently */
68         OBD_SYNCFILTER,  /* XXX temporary, as we play with sync osts.. */
69         OBD_LDLM_TIMEOUT,       /* LDLM timeout for ASTs before client eviction */
70         OBD_DUMP_ON_EVICTION,   /* dump kernel debug log upon eviction */
71         OBD_DEBUG_PEER_ON_TIMEOUT, /* dump peer debug when RPC times out */
72         OBD_ALLOC_FAIL_RATE,    /* memory allocation random failure rate */
73         OBD_MAX_DIRTY_PAGES,    /* maximum dirty pages */
74         OBD_AT_MIN,          /* Adaptive timeouts params */
75         OBD_AT_MAX,
76         OBD_AT_EXTRA,
77         OBD_AT_EARLY_MARGIN,
78         OBD_AT_HISTORY,
79 };
80
81
82 static int proc_set_timeout(struct ctl_table *table, int write,
83                         void __user *buffer, size_t *lenp, loff_t *ppos)
84 {
85         int rc;
86
87         rc = proc_dointvec(table, write, buffer, lenp, ppos);
88         if (ldlm_timeout >= obd_timeout)
89                 ldlm_timeout = max(obd_timeout / 3, 1U);
90         return rc;
91 }
92
93 static int proc_memory_alloc(struct ctl_table *table, int write,
94                         void __user *buffer, size_t *lenp, loff_t *ppos)
95 {
96         char buf[22];
97         int len;
98
99         if (!*lenp || (*ppos && !write)) {
100                 *lenp = 0;
101                 return 0;
102         }
103         if (write)
104                 return -EINVAL;
105
106         len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_sum());
107         if (len > *lenp)
108                 len = *lenp;
109         buf[len] = '\0';
110         if (copy_to_user(buffer, buf, len))
111                 return -EFAULT;
112         *lenp = len;
113         *ppos += *lenp;
114         return 0;
115 }
116
117 static int proc_pages_alloc(struct ctl_table *table, int write,
118                         void __user *buffer, size_t *lenp, loff_t *ppos)
119 {
120         char buf[22];
121         int len;
122
123         if (!*lenp || (*ppos && !write)) {
124                 *lenp = 0;
125                 return 0;
126         }
127         if (write)
128                 return -EINVAL;
129
130         len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_sum());
131         if (len > *lenp)
132                 len = *lenp;
133         buf[len] = '\0';
134         if (copy_to_user(buffer, buf, len))
135                 return -EFAULT;
136         *lenp = len;
137         *ppos += *lenp;
138         return 0;
139 }
140
141 static int proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
142                  size_t *lenp, loff_t *ppos)
143 {
144         char buf[22];
145         int len;
146
147         if (!*lenp || (*ppos && !write)) {
148                 *lenp = 0;
149                 return 0;
150         }
151         if (write)
152                 return -EINVAL;
153
154         len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_max());
155         if (len > *lenp)
156                 len = *lenp;
157         buf[len] = '\0';
158         if (copy_to_user(buffer, buf, len))
159                 return -EFAULT;
160         *lenp = len;
161         *ppos += *lenp;
162         return 0;
163 }
164
165 static int proc_pages_max(struct ctl_table *table, int write,
166                         void __user *buffer, size_t *lenp, loff_t *ppos)
167 {
168         char buf[22];
169         int len;
170
171         if (!*lenp || (*ppos && !write)) {
172                 *lenp = 0;
173                 return 0;
174         }
175         if (write)
176                 return -EINVAL;
177
178         len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_max());
179         if (len > *lenp)
180                 len = *lenp;
181         buf[len] = '\0';
182         if (copy_to_user(buffer, buf, len))
183                 return -EFAULT;
184         *lenp = len;
185         *ppos += *lenp;
186         return 0;
187 }
188
189 static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
190                                void __user *buffer, size_t *lenp, loff_t *ppos)
191 {
192         int rc = 0;
193
194         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
195                 *lenp = 0;
196                 return 0;
197         }
198         if (write) {
199                 rc = lprocfs_write_frac_helper(buffer, *lenp,
200                                                (unsigned int *)table->data,
201                                                1 << (20 - PAGE_CACHE_SHIFT));
202                 /* Don't allow them to let dirty pages exceed 90% of system
203                  * memory and set a hard minimum of 4MB. */
204                 if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
205                         CERROR("Refusing to set max dirty pages to %u, which "
206                                "is more than 90%% of available RAM; setting "
207                                "to %lu\n", obd_max_dirty_pages,
208                                ((totalram_pages / 10) * 9));
209                         obd_max_dirty_pages = ((totalram_pages / 10) * 9);
210                 } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
211                         obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
212                 }
213         } else {
214                 char buf[21];
215                 int len;
216
217                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
218                                                *(unsigned int *)table->data,
219                                                1 << (20 - PAGE_CACHE_SHIFT));
220                 if (len > *lenp)
221                         len = *lenp;
222                 buf[len] = '\0';
223                 if (copy_to_user(buffer, buf, len))
224                         return -EFAULT;
225                 *lenp = len;
226         }
227         *ppos += *lenp;
228         return rc;
229 }
230
231 static int proc_alloc_fail_rate(struct ctl_table *table, int write,
232                          void __user *buffer, size_t *lenp, loff_t *ppos)
233 {
234         int rc    = 0;
235
236         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
237                 *lenp = 0;
238                 return 0;
239         }
240         if (write) {
241                 rc = lprocfs_write_frac_helper(buffer, *lenp,
242                                                (unsigned int *)table->data,
243                                                OBD_ALLOC_FAIL_MULT);
244         } else {
245                 char buf[21];
246                 int  len;
247
248                 len = lprocfs_read_frac_helper(buf, 21,
249                                                *(unsigned int *)table->data,
250                                                OBD_ALLOC_FAIL_MULT);
251                 if (len > *lenp)
252                         len = *lenp;
253                 buf[len] = '\0';
254                 if (copy_to_user(buffer, buf, len))
255                         return -EFAULT;
256                 *lenp = len;
257         }
258         *ppos += *lenp;
259         return rc;
260 }
261
262 #ifdef CONFIG_SYSCTL
263 static struct ctl_table obd_table[] = {
264         {
265                 .procname = "timeout",
266                 .data     = &obd_timeout,
267                 .maxlen   = sizeof(int),
268                 .mode     = 0644,
269                 .proc_handler = &proc_set_timeout
270         },
271         {
272                 .procname = "debug_peer_on_timeout",
273                 .data     = &obd_debug_peer_on_timeout,
274                 .maxlen   = sizeof(int),
275                 .mode     = 0644,
276                 .proc_handler = &proc_dointvec
277         },
278         {
279                 .procname = "dump_on_timeout",
280                 .data     = &obd_dump_on_timeout,
281                 .maxlen   = sizeof(int),
282                 .mode     = 0644,
283                 .proc_handler = &proc_dointvec
284         },
285         {
286                 .procname = "dump_on_eviction",
287                 .data     = &obd_dump_on_eviction,
288                 .maxlen   = sizeof(int),
289                 .mode     = 0644,
290                 .proc_handler = &proc_dointvec
291         },
292         {
293                 .procname = "memused",
294                 .data     = NULL,
295                 .maxlen   = 0,
296                 .mode     = 0444,
297                 .proc_handler = &proc_memory_alloc
298         },
299         {
300                 .procname = "pagesused",
301                 .data     = NULL,
302                 .maxlen   = 0,
303                 .mode     = 0444,
304                 .proc_handler = &proc_pages_alloc
305         },
306         {
307                 .procname = "memused_max",
308                 .data     = NULL,
309                 .maxlen   = 0,
310                 .mode     = 0444,
311                 .proc_handler = &proc_mem_max
312         },
313         {
314                 .procname = "pagesused_max",
315                 .data     = NULL,
316                 .maxlen   = 0,
317                 .mode     = 0444,
318                 .proc_handler = &proc_pages_max
319         },
320         {
321                 .procname = "ldlm_timeout",
322                 .data     = &ldlm_timeout,
323                 .maxlen   = sizeof(int),
324                 .mode     = 0644,
325                 .proc_handler = &proc_set_timeout
326         },
327         {
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         {
335                 .procname = "max_dirty_mb",
336                 .data     = &obd_max_dirty_pages,
337                 .maxlen   = sizeof(int),
338                 .mode     = 0644,
339                 .proc_handler = &proc_max_dirty_pages_in_mb
340         },
341         {
342                 .procname = "at_min",
343                 .data     = &at_min,
344                 .maxlen   = sizeof(int),
345                 .mode     = 0644,
346                 .proc_handler = &proc_dointvec,
347         },
348         {
349                 .procname = "at_max",
350                 .data     = &at_max,
351                 .maxlen   = sizeof(int),
352                 .mode     = 0644,
353                 .proc_handler = &proc_dointvec,
354         },
355         {
356                 .procname = "at_extra",
357                 .data     = &at_extra,
358                 .maxlen   = sizeof(int),
359                 .mode     = 0644,
360                 .proc_handler = &proc_dointvec,
361         },
362         {
363                 .procname = "at_early_margin",
364                 .data     = &at_early_margin,
365                 .maxlen   = sizeof(int),
366                 .mode     = 0644,
367                 .proc_handler = &proc_dointvec,
368         },
369         {
370                 .procname = "at_history",
371                 .data     = &at_history,
372                 .maxlen   = sizeof(int),
373                 .mode     = 0644,
374                 .proc_handler = &proc_dointvec,
375         },
376         {}
377 };
378
379 static struct ctl_table parent_table[] = {
380         {
381                 .procname = "lustre",
382                 .data     = NULL,
383                 .maxlen   = 0,
384                 .mode     = 0555,
385                 .child    = obd_table
386         },
387         {}
388 };
389 #endif
390
391 void obd_sysctl_init(void)
392 {
393 #ifdef CONFIG_SYSCTL
394         if (!obd_table_header)
395                 obd_table_header = register_sysctl_table(parent_table);
396 #endif
397 }
398
399 void obd_sysctl_clean(void)
400 {
401 #ifdef CONFIG_SYSCTL
402         if (obd_table_header)
403                 unregister_sysctl_table(obd_table_header);
404         obd_table_header = NULL;
405 #endif
406 }