Whamcloud - gitweb
af1d19c8dfb09b618a623f15cdd6930de45734fa
[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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2015, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32
33 #include <linux/module.h>
34 #include <linux/sysctl.h>
35 #include <linux/sched.h>
36 #include <linux/mm.h>
37 #include <linux/sysctl.h>
38 #include <linux/version.h>
39 #include <linux/proc_fs.h>
40 #include <linux/slab.h>
41 #include <linux/stat.h>
42 #include <linux/ctype.h>
43 #include <asm/bitops.h>
44 #include <asm/uaccess.h>
45 #include <linux/utsname.h>
46
47 #define DEBUG_SUBSYSTEM S_CLASS
48
49 #include <obd_support.h>
50 #include <lprocfs_status.h>
51 #include <obd_class.h>
52
53 #ifdef CONFIG_SYSCTL
54 static struct ctl_table_header *obd_table_header;
55 #endif
56
57 static int
58 proc_set_timeout(struct ctl_table *table, int write, void __user *buffer,
59                  size_t *lenp, loff_t *ppos)
60 {
61         int rc;
62
63         rc = proc_dointvec(table, write, buffer, lenp, ppos);
64         if (ldlm_timeout >= obd_timeout)
65                 ldlm_timeout = max(obd_timeout / 3, 1U);
66         return rc;
67 }
68
69 static int
70 proc_memory_alloc(struct ctl_table *table, int write, void __user *buffer,
71                   size_t *lenp, loff_t *ppos)
72 {
73         char buf[22];
74         int len;
75
76         if (!*lenp || (*ppos && !write)) {
77                 *lenp = 0;
78                 return 0;
79         }
80         if (write)
81                 return -EINVAL;
82
83         len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_sum());
84         if (len > *lenp)
85                 len = *lenp;
86         buf[len] = '\0';
87         if (copy_to_user(buffer, buf, len))
88                 return -EFAULT;
89         *lenp = len;
90         *ppos += *lenp;
91         return 0;
92 }
93
94 static int
95 proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
96              size_t *lenp, loff_t *ppos)
97 {
98         char buf[22];
99         int len;
100
101         if (!*lenp || (*ppos && !write)) {
102                 *lenp = 0;
103                 return 0;
104         }
105         if (write)
106                 return -EINVAL;
107
108         len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_max());
109         if (len > *lenp)
110                 len = *lenp;
111         buf[len] = '\0';
112         if (copy_to_user(buffer, buf, len))
113                 return -EFAULT;
114         *lenp = len;
115         *ppos += *lenp;
116         return 0;
117 }
118
119 static int
120 proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
121                            void __user *buffer, size_t *lenp, loff_t *ppos)
122 {
123         __s64 val;
124         int rc = 0;
125
126         if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
127                 *lenp = 0;
128                 return 0;
129         }
130         if (write) {
131                 rc = lprocfs_str_with_units_to_s64(buffer, *lenp, &val, 'M');
132                 if (rc)
133                         return rc;
134
135                 if (val < 0)
136                         return -ERANGE;
137
138                 val >>= PAGE_SHIFT;
139
140                 /* Don't allow them to let dirty pages exceed 90% of system
141                  * memory and set a hard minimum of 4MB. */
142                 if (val > ((totalram_pages / 10) * 9)) {
143                         CERROR("Refusing to set max dirty pages to %lld, "
144                                "which is more than 90%% of available RAM; "
145                                "setting to %lu\n", val,
146                                ((totalram_pages / 10) * 9));
147                         obd_max_dirty_pages = ((totalram_pages / 10) * 9);
148                 } else if (val < 4 << (20 - PAGE_SHIFT)) {
149                         obd_max_dirty_pages = 4 << (20 - PAGE_SHIFT);
150                 } else {
151                         obd_max_dirty_pages = val;
152                 }
153         } else {
154                 char buf[21];
155                 int len;
156
157                 len = lprocfs_read_frac_helper(buf, sizeof(buf),
158                                                *(unsigned long *)table->data,
159                                                1 << (20 - PAGE_SHIFT));
160                 if (len > *lenp)
161                         len = *lenp;
162                 buf[len] = '\0';
163                 if (copy_to_user(buffer, buf, len))
164                         return -EFAULT;
165                 *lenp = len;
166         }
167         *ppos += *lenp;
168         return rc;
169 }
170
171 #ifdef CONFIG_SYSCTL
172 static struct ctl_table obd_table[] = {
173         {
174                 INIT_CTL_NAME
175                 .procname       = "timeout",
176                 .data           = &obd_timeout,
177                 .maxlen         = sizeof(int),
178                 .mode           = 0644,
179                 .proc_handler   = &proc_set_timeout
180         },
181         {
182                 INIT_CTL_NAME
183                 .procname       = "debug_peer_on_timeout",
184                 .data           = &obd_debug_peer_on_timeout,
185                 .maxlen         = sizeof(int),
186                 .mode           = 0644,
187                 .proc_handler   = &proc_dointvec
188         },
189         {
190                 INIT_CTL_NAME
191                 .procname       = "dump_on_timeout",
192                 .data           = &obd_dump_on_timeout,
193                 .maxlen         = sizeof(int),
194                 .mode           = 0644,
195                 .proc_handler   = &proc_dointvec
196         },
197         {
198                 INIT_CTL_NAME
199                 .procname       = "dump_on_eviction",
200                 .data           = &obd_dump_on_eviction,
201                 .maxlen         = sizeof(int),
202                 .mode           = 0644,
203                 .proc_handler   = &proc_dointvec
204         },
205         {
206                 INIT_CTL_NAME
207                 .procname       = "memused",
208                 .data           = NULL,
209                 .maxlen         = 0,
210                 .mode           = 0444,
211                 .proc_handler   = &proc_memory_alloc
212         },
213         {
214                 INIT_CTL_NAME
215                 .procname       = "memused_max",
216                 .data           = NULL,
217                 .maxlen         = 0,
218                 .mode           = 0444,
219                 .proc_handler   = &proc_mem_max
220         },
221         {
222                 INIT_CTL_NAME
223                 .procname       = "ldlm_timeout",
224                 .data           = &ldlm_timeout,
225                 .maxlen         = sizeof(int),
226                 .mode           = 0644,
227                 .proc_handler   = &proc_set_timeout
228         },
229         {
230                 INIT_CTL_NAME
231                 .procname       = "max_dirty_mb",
232                 .data           = &obd_max_dirty_pages,
233                 .maxlen         = sizeof(unsigned long),
234                 .mode           = 0644,
235                 .proc_handler   = &proc_max_dirty_pages_in_mb
236         },
237         {
238                 INIT_CTL_NAME
239                 .procname       = "bulk_timeout",
240                 .data           = &bulk_timeout,
241                 .maxlen         = sizeof(int),
242                 .mode           = 0644,
243                 .proc_handler   = &proc_dointvec
244         },
245         {
246                 INIT_CTL_NAME
247                 .procname       = "at_min",
248                 .data           = &at_min,
249                 .maxlen         = sizeof(int),
250                 .mode           = 0644,
251                 .proc_handler   = &proc_dointvec
252         },
253         {
254                 INIT_CTL_NAME
255                 .procname       = "at_max",
256                 .data           = &at_max,
257                 .maxlen         = sizeof(int),
258                 .mode           = 0644,
259                 .proc_handler   = &proc_dointvec
260         },
261         {
262                 INIT_CTL_NAME
263                 .procname       = "at_extra",
264                 .data           = &at_extra,
265                 .maxlen         = sizeof(int),
266                 .mode           = 0644,
267                 .proc_handler   = &proc_dointvec
268         },
269         {
270                 INIT_CTL_NAME
271                 .procname       = "at_early_margin",
272                 .data           = &at_early_margin,
273                 .maxlen         = sizeof(int),
274                 .mode           = 0644,
275                 .proc_handler   = &proc_dointvec
276         },
277         {
278                 INIT_CTL_NAME
279                 .procname       = "at_history",
280                 .data           = &at_history,
281                 .maxlen         = sizeof(int),
282                 .mode           = 0644,
283                 .proc_handler   = &proc_dointvec
284         },
285         { 0 }
286 };
287
288 static struct ctl_table parent_table[] = {
289         {
290                 INIT_CTL_NAME
291                 .procname       = "lustre",
292                 .data           = NULL,
293                 .maxlen         = 0,
294                 .mode           = 0555,
295                 .child          = obd_table
296         },
297         { 0 }
298 };
299 #endif
300
301 void obd_sysctl_init (void)
302 {
303 #ifdef CONFIG_SYSCTL
304         if ( !obd_table_header )
305                 obd_table_header = register_sysctl_table(parent_table);
306 #endif
307 }
308
309 void obd_sysctl_clean (void)
310 {
311 #ifdef CONFIG_SYSCTL
312         if ( obd_table_header )
313                 unregister_sysctl_table(obd_table_header);
314         obd_table_header = NULL;
315 #endif
316 }