Whamcloud - gitweb
LU-6068 misc: update Intel copyright messages 2014
[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 "gnilnd.h"
30
31 #define GNILND_PEERSTATE_STRLEN 16
32 typedef struct kgn_sysctl_data {
33         int                     ksd_pause_trigger;
34         int                     ksd_quiesce_secs;
35         int                     ksd_rdmaq_override;
36         char                    ksd_peer_state[GNILND_PEERSTATE_STRLEN];
37 } kgn_sysctl_data_t;
38
39 static kgn_sysctl_data_t        kgnilnd_sysctl;
40
41 #if defined(CONFIG_SYSCTL)
42
43 static struct ctl_table_header *kgnilnd_table_header = NULL;
44
45 static int
46 proc_toggle_thread_pause(struct ctl_table *table, int write,
47                          void __user *buffer, size_t *lenp, loff_t *ppos)
48 {
49         int  old_val = kgnilnd_sysctl.ksd_pause_trigger;
50         int  rc = 0;
51         ENTRY;
52
53         rc = proc_dointvec(table, write, buffer, lenp, ppos);
54         if (!write) {
55                 /* read */
56                 RETURN(rc);
57         }
58
59         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
60                 rc = -EINVAL;
61                 RETURN(rc);
62         }
63
64         if (old_val != kgnilnd_sysctl.ksd_pause_trigger) {
65                 mutex_lock(&kgnilnd_data.kgn_quiesce_mutex);
66                 CDEBUG(D_NET, "setting quiesce_trigger %d\n", old_val);
67                 kgnilnd_data.kgn_quiesce_trigger = kgnilnd_sysctl.ksd_pause_trigger;
68                 kgnilnd_quiesce_wait("admin sysctl");
69                 mutex_unlock(&kgnilnd_data.kgn_quiesce_mutex);
70         }
71
72         RETURN(rc);
73 }
74
75 static int
76 proc_hw_quiesce(struct ctl_table *table, int write, void __user *buffer,
77                 size_t *lenp, loff_t *ppos)
78 {
79         int              rc = 0;
80         kgn_device_t    *dev;
81         ENTRY;
82
83         rc = proc_dointvec(table, write, buffer, lenp, ppos);
84         if (!write) {
85                 /* read */
86                 RETURN(rc);
87         }
88
89         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
90                 rc = -EINVAL;
91                 RETURN(rc);
92         }
93
94
95         /* only device 0 gets the handle, see kgnilnd_dev_init */
96         dev = &kgnilnd_data.kgn_devices[0];
97
98         LASSERTF(dev != NULL, "dev 0 is NULL\n");
99
100         kgnilnd_quiesce_end_callback(dev->gnd_handle,
101                                      kgnilnd_sysctl.ksd_quiesce_secs * MSEC_PER_SEC);
102
103         RETURN(rc);
104 }
105
106 static int
107 proc_trigger_stack_reset(struct ctl_table *table, int write,
108                          void __user *buffer, size_t *lenp, loff_t *ppos)
109 {
110         int              rc = 0;
111         int              i = 1;
112         kgn_device_t    *dev;
113         ENTRY;
114
115         if (!write) {
116                 /* read */
117                 rc = proc_dointvec(table, write, buffer, lenp, ppos);
118                 RETURN(rc);
119         }
120
121         /* only device 0 gets the handle, see kgnilnd_dev_init */
122         dev = &kgnilnd_data.kgn_devices[0];
123
124         LASSERTF(dev != NULL, "dev 0 is NULL\n");
125
126         kgnilnd_critical_error(dev->gnd_err_handle);
127
128         /* Wait for the reset to complete.  This prevents any races in testing
129          * where we'd immediately try to send traffic again */
130         while (kgnilnd_data.kgn_needs_reset != 0) {
131                 i++;
132                 LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
133                                 "Waiting for stack reset request to clear\n");
134                 cfs_pause(cfs_time_seconds(1 * i));
135         }
136
137         RETURN(rc);
138 }
139
140 static int
141 proc_toggle_rdmaq_override(struct ctl_table *table, int write,
142                            void __user *buffer, size_t *lenp, loff_t *ppos)
143 {
144         int  old_val = kgnilnd_sysctl.ksd_rdmaq_override;
145         int  rc = 0;
146         ENTRY;
147
148         rc = proc_dointvec(table, write, buffer, lenp, ppos);
149         if (!write) {
150                 /* read */
151                 RETURN(rc);
152         }
153
154         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
155                 rc = -EINVAL;
156                 RETURN(rc);
157         }
158
159         if (old_val != kgnilnd_sysctl.ksd_rdmaq_override) {
160                 long    new_mb = kgnilnd_sysctl.ksd_rdmaq_override * (long)(1024*1024);
161                 LCONSOLE_INFO("changing RDMAQ override to %d mbytes/sec\n",
162                               kgnilnd_sysctl.ksd_rdmaq_override);
163                 /* override proc is mbytes, but we calc in bytes */
164                 kgnilnd_data.kgn_rdmaq_override = new_mb;
165                 smp_wmb();
166         }
167
168         RETURN(rc);
169 }
170
171 /* /proc/sys entry point for injecting up/down nid event
172  * <up|down> <nid>
173  */
174 static int
175 proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
176                 size_t *lenp, loff_t *ppos)
177 {
178         int             rc;
179         int             nid;
180         int             node_down;
181         char            command[10];
182         ENTRY;
183
184         rc = proc_dostring(table, write, buffer, lenp, ppos);
185
186         if (!write) {
187                 /* read */
188                 RETURN(rc);
189         }
190
191         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
192                 rc = -EINVAL;
193                 RETURN(rc);
194         }
195
196         /* convert to nid, up/down values */
197         rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
198         CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);
199
200         if (rc != 2) {
201                 CDEBUG(D_ERROR, "invalid parameter\n");
202                 RETURN(rc);
203         } else {
204                 switch (command[0]) {
205                 case 'd': /* down */
206                         node_down = 1;
207                         CDEBUG(D_INFO, "take node %d down\n", nid);
208                         break;
209                 case 'u': /* up */
210                         node_down = 0;
211                         CDEBUG(D_INFO, "bring node %d up\n", nid);
212                         break;
213                 default:
214                         CDEBUG(D_ERROR, "invalid command %s\n", command);
215                         RETURN(-EINVAL);
216                 }
217         }
218
219         CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
220                       node_down, nid);
221         rc = kgnilnd_report_node_state(nid, node_down);
222
223         if (rc) {
224                 rc = -EINVAL;
225         }
226
227         RETURN(rc);
228 }
229
230 static struct ctl_table kgnilnd_table[] = {
231         /*
232          * NB No .strategy entries have been provided since sysctl(8) prefers
233          * to go via /proc for portability.
234          */
235         {
236                 INIT_CTL_NAME
237                 .procname = "version",
238                 .data     = KGNILND_BUILD_REV,
239                 .maxlen   = sizeof(KGNILND_BUILD_REV),
240                 .mode     = 0444,
241                 .proc_handler = &proc_dostring
242         },
243         {
244                 INIT_CTL_NAME
245                 .procname = "thread_pause",
246                 .data     = &kgnilnd_sysctl.ksd_pause_trigger,
247                 .maxlen   = sizeof(int),
248                 .mode     = 0644,
249                 .proc_handler = &proc_toggle_thread_pause,
250         },
251         {
252                 INIT_CTL_NAME
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                 INIT_CTL_NAME
261                 .procname = "stack_reset",
262                 .data     = NULL,
263                 .maxlen   = sizeof(int),
264                 .mode     = 0600,
265                 .proc_handler = &proc_trigger_stack_reset,
266         },
267         {
268                 INIT_CTL_NAME
269                 .procname = "rdmaq_override",
270                 .data     = &kgnilnd_sysctl.ksd_rdmaq_override,
271                 .maxlen   = sizeof(int),
272                 .mode     = 0644,
273                 .proc_handler = &proc_toggle_rdmaq_override,
274         },
275         {
276                 INIT_CTL_NAME
277                 .procname = "peer_state",
278                 .data     = kgnilnd_sysctl.ksd_peer_state,
279                 .maxlen   = GNILND_PEERSTATE_STRLEN,
280                 .mode     = 0644,
281                 .proc_handler = &proc_peer_state,
282         },
283         { 0 }
284 };
285
286 static struct ctl_table kgnilnd_top_table[2] = {
287         {
288                 INIT_CTL_NAME
289                 .procname = "kgnilnd",
290                 .data     = NULL,
291                 .maxlen   = 0,
292                 .mode     = 0555,
293                 .child    = kgnilnd_table
294         },
295         { 0 }
296 };
297
298 void kgnilnd_insert_sysctl(void)
299 {
300         if (kgnilnd_table_header == NULL)
301                 kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
302 }
303
304 void kgnilnd_remove_sysctl(void)
305 {
306         if (kgnilnd_table_header != NULL)
307                 unregister_sysctl_table(kgnilnd_table_header);
308
309         kgnilnd_table_header = NULL;
310 }
311
312 #else
313 void kgnilnd_insert_sysctl(void) {}
314 void kgnilnd_remove_sysctl(void) {}
315 #endif