OSDN Git Service

staging: lustre: Coalesce string fragments
[android-x86/kernel.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 is more than 90%% of available RAM; setting to %lu\n",
206                                obd_max_dirty_pages,
207                                ((totalram_pages / 10) * 9));
208                         obd_max_dirty_pages = ((totalram_pages / 10) * 9);
209                 } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
210                         obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
211                 }
212         } else {
213                 char buf[21];
214                 int len;
215
216                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
217                                                *(unsigned int *)table->data,
218                                                1 << (20 - PAGE_CACHE_SHIFT));
219                 if (len > *lenp)
220                         len = *lenp;
221                 buf[len] = '\0';
222                 if (copy_to_user(buffer, buf, len))
223                         return -EFAULT;
224                 *lenp = len;
225         }
226         *ppos += *lenp;
227         return rc;
228 }
229
230 static int proc_alloc_fail_rate(struct ctl_table *table, int write,
231                          void __user *buffer, size_t *lenp, loff_t *ppos)
232 {
233         int rc    = 0;
234
235         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
236                 *lenp = 0;
237                 return 0;
238         }
239         if (write) {
240                 rc = lprocfs_write_frac_helper(buffer, *lenp,
241                                                (unsigned int *)table->data,
242                                                OBD_ALLOC_FAIL_MULT);
243         } else {
244                 char buf[21];
245                 int  len;
246
247                 len = lprocfs_read_frac_helper(buf, 21,
248                                                *(unsigned int *)table->data,
249                                                OBD_ALLOC_FAIL_MULT);
250                 if (len > *lenp)
251                         len = *lenp;
252                 buf[len] = '\0';
253                 if (copy_to_user(buffer, buf, len))
254                         return -EFAULT;
255                 *lenp = len;
256         }
257         *ppos += *lenp;
258         return rc;
259 }
260
261 #ifdef CONFIG_SYSCTL
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 }