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