Whamcloud - gitweb
LU-12477 libcfs: Remove obsolete config checks
[fs/lustre-release.git] / lnet / klnds / gnilnd / gnilnd_sysctl.c
1 /*
2  * Copyright (C) 2012 Cray, Inc.
3  *
4  * Copyright (c) 2014, Intel Corporation.
5  *
6  *   Author: Nic Henke <nic@cray.com>
7  *   Author: James Shimek <jshimek@cray.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 /* this code liberated and modified from Lustre */
26
27 #define DEBUG_SUBSYSTEM S_LND
28
29 #include <libcfs/linux/linux-misc.h>
30
31 #include "gnilnd.h"
32
33 #define GNILND_PEERSTATE_STRLEN 16
34 typedef struct kgn_sysctl_data {
35         int                     ksd_pause_trigger;
36         int                     ksd_quiesce_secs;
37         int                     ksd_rdmaq_override;
38         char                    ksd_peer_state[GNILND_PEERSTATE_STRLEN];
39 } kgn_sysctl_data_t;
40
41 static kgn_sysctl_data_t        kgnilnd_sysctl;
42
43 #if defined(CONFIG_SYSCTL)
44
45 static struct ctl_table_header *kgnilnd_table_header = NULL;
46
47 static int
48 proc_toggle_thread_pause(struct ctl_table *table, int write,
49                          void __user *buffer, size_t *lenp, loff_t *ppos)
50 {
51         int  old_val = kgnilnd_sysctl.ksd_pause_trigger;
52         int  rc = 0;
53         ENTRY;
54
55         rc = proc_dointvec(table, write, buffer, lenp, ppos);
56         if (!write) {
57                 /* read */
58                 RETURN(rc);
59         }
60
61         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
62                 rc = -EINVAL;
63                 RETURN(rc);
64         }
65
66         if (old_val != kgnilnd_sysctl.ksd_pause_trigger) {
67                 mutex_lock(&kgnilnd_data.kgn_quiesce_mutex);
68                 CDEBUG(D_NET, "setting quiesce_trigger %d\n", old_val);
69                 kgnilnd_data.kgn_quiesce_trigger = kgnilnd_sysctl.ksd_pause_trigger;
70                 kgnilnd_quiesce_wait("admin sysctl");
71                 mutex_unlock(&kgnilnd_data.kgn_quiesce_mutex);
72         }
73
74         RETURN(rc);
75 }
76
77 static int
78 proc_hw_quiesce(struct ctl_table *table, int write, void __user *buffer,
79                 size_t *lenp, loff_t *ppos)
80 {
81         int              rc = 0;
82         kgn_device_t    *dev;
83         ENTRY;
84
85         rc = proc_dointvec(table, write, buffer, lenp, ppos);
86         if (!write) {
87                 /* read */
88                 RETURN(rc);
89         }
90
91         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
92                 rc = -EINVAL;
93                 RETURN(rc);
94         }
95
96
97         /* only device 0 gets the handle, see kgnilnd_dev_init */
98         dev = &kgnilnd_data.kgn_devices[0];
99
100         LASSERTF(dev != NULL, "dev 0 is NULL\n");
101
102         kgnilnd_quiesce_end_callback(dev->gnd_handle,
103                                      kgnilnd_sysctl.ksd_quiesce_secs * MSEC_PER_SEC);
104
105         RETURN(rc);
106 }
107
108 static int
109 proc_trigger_stack_reset(struct ctl_table *table, int write,
110                          void __user *buffer, size_t *lenp, loff_t *ppos)
111 {
112         int              rc = 0;
113         int              i = 1;
114         kgn_device_t    *dev;
115         ENTRY;
116
117         if (!write) {
118                 /* read */
119                 rc = proc_dointvec(table, write, buffer, lenp, ppos);
120                 RETURN(rc);
121         }
122
123         /* only device 0 gets the handle, see kgnilnd_dev_init */
124         dev = &kgnilnd_data.kgn_devices[0];
125
126         LASSERTF(dev != NULL, "dev 0 is NULL\n");
127
128         kgnilnd_critical_error(dev->gnd_err_handle);
129
130         /* Wait for the reset to complete.  This prevents any races in testing
131          * where we'd immediately try to send traffic again */
132         while (kgnilnd_data.kgn_needs_reset != 0) {
133                 i++;
134                 LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
135                                 "Waiting for stack reset request to clear\n");
136                 set_current_state(TASK_UNINTERRUPTIBLE);
137                 schedule_timeout(cfs_time_seconds(1 * i));
138         }
139
140         RETURN(rc);
141 }
142
143 static int
144 proc_toggle_rdmaq_override(struct ctl_table *table, int write,
145                            void __user *buffer, size_t *lenp, loff_t *ppos)
146 {
147         int  old_val = kgnilnd_sysctl.ksd_rdmaq_override;
148         int  rc = 0;
149         ENTRY;
150
151         rc = proc_dointvec(table, write, buffer, lenp, ppos);
152         if (!write) {
153                 /* read */
154                 RETURN(rc);
155         }
156
157         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
158                 rc = -EINVAL;
159                 RETURN(rc);
160         }
161
162         if (old_val != kgnilnd_sysctl.ksd_rdmaq_override) {
163                 long    new_mb = kgnilnd_sysctl.ksd_rdmaq_override * (long)(1024*1024);
164                 LCONSOLE_INFO("changing RDMAQ override to %d mbytes/sec\n",
165                               kgnilnd_sysctl.ksd_rdmaq_override);
166                 /* override proc is mbytes, but we calc in bytes */
167                 kgnilnd_data.kgn_rdmaq_override = new_mb;
168                 smp_wmb();
169         }
170
171         RETURN(rc);
172 }
173
174 /* /proc/sys entry point for injecting up/down nid event
175  * <up|down> <nid>
176  */
177 static int
178 proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
179                 size_t *lenp, loff_t *ppos)
180 {
181         int             rc;
182         int             nid;
183         int             node_down;
184         char            command[10];
185         ENTRY;
186
187         rc = proc_dostring(table, write, buffer, lenp, ppos);
188
189         if (!write) {
190                 /* read */
191                 RETURN(rc);
192         }
193
194         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
195                 rc = -EINVAL;
196                 RETURN(rc);
197         }
198
199         /* convert to nid, up/down values */
200         rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
201         CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);
202
203         if (rc != 2) {
204                 CDEBUG(D_ERROR, "invalid parameter\n");
205                 RETURN(rc);
206         } else {
207                 switch (command[0]) {
208                 case 'd': /* down */
209                         node_down = 1;
210                         CDEBUG(D_INFO, "take node %d down\n", nid);
211                         break;
212                 case 'u': /* up */
213                         node_down = 0;
214                         CDEBUG(D_INFO, "bring node %d up\n", nid);
215                         break;
216                 default:
217                         CDEBUG(D_ERROR, "invalid command %s\n", command);
218                         RETURN(-EINVAL);
219                 }
220         }
221
222         CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
223                       node_down, nid);
224         rc = kgnilnd_report_node_state(nid, node_down);
225
226         if (rc) {
227                 rc = -EINVAL;
228         }
229
230         RETURN(rc);
231 }
232
233 static struct ctl_table kgnilnd_table[] = {
234         /*
235          * NB No .strategy entries have been provided since sysctl(8) prefers
236          * to go via /proc for portability.
237          */
238         {
239                 .procname = "version",
240                 .data     = LUSTRE_VERSION_STRING,
241                 .maxlen   = sizeof(LUSTRE_VERSION_STRING),
242                 .mode     = 0444,
243                 .proc_handler = &proc_dostring
244         },
245         {
246                 .procname = "thread_pause",
247                 .data     = &kgnilnd_sysctl.ksd_pause_trigger,
248                 .maxlen   = sizeof(int),
249                 .mode     = 0644,
250                 .proc_handler = &proc_toggle_thread_pause,
251         },
252         {
253                 .procname = "hw_quiesce",
254                 .data     = &kgnilnd_sysctl.ksd_quiesce_secs,
255                 .maxlen   = sizeof(__u32),
256                 .mode     = 0644,
257                 .proc_handler = &proc_hw_quiesce,
258         },
259         {
260                 .procname = "stack_reset",
261                 .data     = NULL,
262                 .maxlen   = sizeof(int),
263                 .mode     = 0600,
264                 .proc_handler = &proc_trigger_stack_reset,
265         },
266         {
267                 .procname = "rdmaq_override",
268                 .data     = &kgnilnd_sysctl.ksd_rdmaq_override,
269                 .maxlen   = sizeof(int),
270                 .mode     = 0644,
271                 .proc_handler = &proc_toggle_rdmaq_override,
272         },
273         {
274                 .procname = "peer_state",
275                 .data     = kgnilnd_sysctl.ksd_peer_state,
276                 .maxlen   = GNILND_PEERSTATE_STRLEN,
277                 .mode     = 0644,
278                 .proc_handler = &proc_peer_state,
279         },
280         { 0 }
281 };
282
283 static struct ctl_table kgnilnd_top_table[2] = {
284         {
285                 .procname = "kgnilnd",
286                 .data     = NULL,
287                 .maxlen   = 0,
288                 .mode     = 0555,
289                 .child    = kgnilnd_table
290         },
291         { 0 }
292 };
293
294 void kgnilnd_insert_sysctl(void)
295 {
296         if (kgnilnd_table_header == NULL)
297                 kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
298 }
299
300 void kgnilnd_remove_sysctl(void)
301 {
302         if (kgnilnd_table_header != NULL)
303                 unregister_sysctl_table(kgnilnd_table_header);
304
305         kgnilnd_table_header = NULL;
306 }
307
308 #else
309 void kgnilnd_insert_sysctl(void) {}
310 void kgnilnd_remove_sysctl(void) {}
311 #endif