Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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 #ifdef CONFIG_SYSCTL
83 static int proc_set_timeout(struct ctl_table *table, int write,
84                         void __user *buffer, size_t *lenp, loff_t *ppos)
85 {
86         int rc;
87
88         rc = proc_dointvec(table, write, buffer, lenp, ppos);
89         if (ldlm_timeout >= obd_timeout)
90                 ldlm_timeout = max(obd_timeout / 3, 1U);
91         return rc;
92 }
93
94 static int proc_memory_alloc(struct ctl_table *table, int write,
95                         void __user *buffer, size_t *lenp, loff_t *ppos)
96 {
97         char buf[22];
98         int len;
99
100         if (!*lenp || (*ppos && !write)) {
101                 *lenp = 0;
102                 return 0;
103         }
104         if (write)
105                 return -EINVAL;
106
107         len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_sum());
108         if (len > *lenp)
109                 len = *lenp;
110         buf[len] = '\0';
111         if (copy_to_user(buffer, buf, len))
112                 return -EFAULT;
113         *lenp = len;
114         *ppos += *lenp;
115         return 0;
116 }
117
118 static int proc_pages_alloc(struct ctl_table *table, int write,
119                         void __user *buffer, size_t *lenp, loff_t *ppos)
120 {
121         char buf[22];
122         int len;
123
124         if (!*lenp || (*ppos && !write)) {
125                 *lenp = 0;
126                 return 0;
127         }
128         if (write)
129                 return -EINVAL;
130
131         len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_sum());
132         if (len > *lenp)
133                 len = *lenp;
134         buf[len] = '\0';
135         if (copy_to_user(buffer, buf, len))
136                 return -EFAULT;
137         *lenp = len;
138         *ppos += *lenp;
139         return 0;
140 }
141
142 static int proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
143                  size_t *lenp, loff_t *ppos)
144 {
145         char buf[22];
146         int len;
147
148         if (!*lenp || (*ppos && !write)) {
149                 *lenp = 0;
150                 return 0;
151         }
152         if (write)
153                 return -EINVAL;
154
155         len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_max());
156         if (len > *lenp)
157                 len = *lenp;
158         buf[len] = '\0';
159         if (copy_to_user(buffer, buf, len))
160                 return -EFAULT;
161         *lenp = len;
162         *ppos += *lenp;
163         return 0;
164 }
165
166 static int proc_pages_max(struct ctl_table *table, int write,
167                         void __user *buffer, size_t *lenp, loff_t *ppos)
168 {
169         char buf[22];
170         int len;
171
172         if (!*lenp || (*ppos && !write)) {
173                 *lenp = 0;
174                 return 0;
175         }
176         if (write)
177                 return -EINVAL;
178
179         len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_max());
180         if (len > *lenp)
181                 len = *lenp;
182         buf[len] = '\0';
183         if (copy_to_user(buffer, buf, len))
184                 return -EFAULT;
185         *lenp = len;
186         *ppos += *lenp;
187         return 0;
188 }
189
190 static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
191                                void __user *buffer, size_t *lenp, loff_t *ppos)
192 {
193         int rc = 0;
194
195         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
196                 *lenp = 0;
197                 return 0;
198         }
199         if (write) {
200                 rc = lprocfs_write_frac_helper(buffer, *lenp,
201                                                (unsigned int *)table->data,
202                                                1 << (20 - PAGE_CACHE_SHIFT));
203                 /* Don't allow them to let dirty pages exceed 90% of system
204                  * memory and set a hard minimum of 4MB. */
205                 if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
206                         CERROR("Refusing to set max dirty pages to %u, which is more than 90%% of available RAM; setting to %lu\n",
207                                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 static struct ctl_table obd_table[] = {
263         {
264                 .procname = "timeout",
265                 .data     = &obd_timeout,
266                 .maxlen   = sizeof(int),
267                 .mode     = 0644,
268                 .proc_handler = &proc_set_timeout
269         },
270         {
271                 .procname = "debug_peer_on_timeout",
272                 .data     = &obd_debug_peer_on_timeout,
273                 .maxlen   = sizeof(int),
274                 .mode     = 0644,
275                 .proc_handler = &proc_dointvec
276         },
277         {
278                 .procname = "dump_on_timeout",
279                 .data     = &obd_dump_on_timeout,
280                 .maxlen   = sizeof(int),
281                 .mode     = 0644,
282                 .proc_handler = &proc_dointvec
283         },
284         {
285                 .procname = "dump_on_eviction",
286                 .data     = &obd_dump_on_eviction,
287                 .maxlen   = sizeof(int),
288                 .mode     = 0644,
289                 .proc_handler = &proc_dointvec
290         },
291         {
292                 .procname = "memused",
293                 .data     = NULL,
294                 .maxlen   = 0,
295                 .mode     = 0444,
296                 .proc_handler = &proc_memory_alloc
297         },
298         {
299                 .procname = "pagesused",
300                 .data     = NULL,
301                 .maxlen   = 0,
302                 .mode     = 0444,
303                 .proc_handler = &proc_pages_alloc
304         },
305         {
306                 .procname = "memused_max",
307                 .data     = NULL,
308                 .maxlen   = 0,
309                 .mode     = 0444,
310                 .proc_handler = &proc_mem_max
311         },
312         {
313                 .procname = "pagesused_max",
314                 .data     = NULL,
315                 .maxlen   = 0,
316                 .mode     = 0444,
317                 .proc_handler = &proc_pages_max
318         },
319         {
320                 .procname = "ldlm_timeout",
321                 .data     = &ldlm_timeout,
322                 .maxlen   = sizeof(int),
323                 .mode     = 0644,
324                 .proc_handler = &proc_set_timeout
325         },
326         {
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         {
334                 .procname = "max_dirty_mb",
335                 .data     = &obd_max_dirty_pages,
336                 .maxlen   = sizeof(int),
337                 .mode     = 0644,
338                 .proc_handler = &proc_max_dirty_pages_in_mb
339         },
340         {
341                 .procname = "at_min",
342                 .data     = &at_min,
343                 .maxlen   = sizeof(int),
344                 .mode     = 0644,
345                 .proc_handler = &proc_dointvec,
346         },
347         {
348                 .procname = "at_max",
349                 .data     = &at_max,
350                 .maxlen   = sizeof(int),
351                 .mode     = 0644,
352                 .proc_handler = &proc_dointvec,
353         },
354         {
355                 .procname = "at_extra",
356                 .data     = &at_extra,
357                 .maxlen   = sizeof(int),
358                 .mode     = 0644,
359                 .proc_handler = &proc_dointvec,
360         },
361         {
362                 .procname = "at_early_margin",
363                 .data     = &at_early_margin,
364                 .maxlen   = sizeof(int),
365                 .mode     = 0644,
366                 .proc_handler = &proc_dointvec,
367         },
368         {
369                 .procname = "at_history",
370                 .data     = &at_history,
371                 .maxlen   = sizeof(int),
372                 .mode     = 0644,
373                 .proc_handler = &proc_dointvec,
374         },
375         {}
376 };
377
378 static struct ctl_table parent_table[] = {
379         {
380                 .procname = "lustre",
381                 .data     = NULL,
382                 .maxlen   = 0,
383                 .mode     = 0555,
384                 .child    = obd_table
385         },
386         {}
387 };
388 #endif
389
390 void obd_sysctl_init(void)
391 {
392 #ifdef CONFIG_SYSCTL
393         if (!obd_table_header)
394                 obd_table_header = register_sysctl_table(parent_table);
395 #endif
396 }
397
398 void obd_sysctl_clean(void)
399 {
400 #ifdef CONFIG_SYSCTL
401         if (obd_table_header)
402                 unregister_sysctl_table(obd_table_header);
403         obd_table_header = NULL;
404 #endif
405 }