Whamcloud - gitweb
LU-1346 libcfs: remove cfs_ file wrappers
[fs/lustre-release.git] / lnet / klnds / gnilnd / gnilnd_sysctl.c
1 /*
2  * Copyright (C) 2012 Cray, Inc.
3  *
4  *   Author: Nic Henke <nic@cray.com>
5  *   Author: James Shimek <jshimek@cray.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
9  *   Lustre is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Lustre is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Lustre; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 /* this code liberated and modified from Lustre */
24
25 #define DEBUG_SUBSYSTEM S_LND
26
27 #include "gnilnd.h"
28
29 typedef struct kgn_sysctl_data {
30         int                     ksd_pause_trigger;
31         int                     ksd_quiesce_secs;
32         int                     ksd_rdmaq_override;
33 } kgn_sysctl_data_t;
34
35 static kgn_sysctl_data_t        kgnilnd_sysctl;
36
37 #if defined(CONFIG_SYSCTL)
38
39 static cfs_sysctl_table_header_t *kgnilnd_table_header = NULL;
40 #ifndef HAVE_SYSCTL_UNNUMBERED
41
42 enum {
43         GNILND_VERSION = 1,
44         GNILND_THREAD_PAUSE,
45         GNILND_HW_QUIESCE,
46         GNILND_STACK_RESET,
47         GNILND_RDMAQ_OVERRIDE,
48 };
49 #else
50 #define GNILND_VERSION             CTL_UNNUMBERED
51 #define GNILND_THREAD_PAUSE        CTL_UNNUMBERED
52 #define GNILND_HW_QUIESCE          CTL_UNNUMBERED
53 #define GNILND_STACK_RESET         CTL_UNNUMBERED
54 #define GNILND_RDMAQ_OVERRIDE      CTL_UNNUMBERED
55 #endif
56
57 static int LL_PROC_PROTO(proc_toggle_thread_pause)
58 {
59         int  old_val = kgnilnd_sysctl.ksd_pause_trigger;
60         int  rc = 0;
61         ENTRY;
62
63         rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
64         if (!write) {
65                 /* read */
66                 RETURN(rc);
67         }
68
69         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
70                 rc = -EINVAL;
71                 RETURN(rc);
72         }
73
74         if (old_val != kgnilnd_sysctl.ksd_pause_trigger) {
75                 down(&kgnilnd_data.kgn_quiesce_sem);
76                 CDEBUG(D_NET, "setting quiesce_trigger %d\n", old_val);
77                 kgnilnd_data.kgn_quiesce_trigger = kgnilnd_sysctl.ksd_pause_trigger;
78                 kgnilnd_quiesce_wait("admin sysctl");
79                 up(&kgnilnd_data.kgn_quiesce_sem);
80         }
81
82         RETURN(rc);
83 }
84
85 static int LL_PROC_PROTO(proc_hw_quiesce)
86 {
87         int              rc = 0;
88         kgn_device_t    *dev;
89         ENTRY;
90
91         rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
92         if (!write) {
93                 /* read */
94                 RETURN(rc);
95         }
96
97         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
98                 rc = -EINVAL;
99                 RETURN(rc);
100         }
101
102
103         /* only device 0 gets the handle, see kgnilnd_dev_init */
104         dev = &kgnilnd_data.kgn_devices[0];
105
106         LASSERTF(dev != NULL, "dev 0 is NULL\n");
107
108         kgnilnd_quiesce_end_callback(dev->gnd_handle,
109                                      kgnilnd_sysctl.ksd_quiesce_secs * MSEC_PER_SEC);
110
111         RETURN(rc);
112 }
113
114 int LL_PROC_PROTO(proc_trigger_stack_reset)
115 {
116         int              rc = 0;
117         int                i = 1;
118        kgn_device_t    *dev;
119         ENTRY;
120
121         if (!write) {
122                 /* read */
123                 rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
124                 RETURN(rc);
125         }
126
127         /* only device 0 gets the handle, see kgnilnd_dev_init */
128         dev = &kgnilnd_data.kgn_devices[0];
129
130         LASSERTF(dev != NULL, "dev 0 is NULL\n");
131
132         kgnilnd_critical_error(dev->gnd_err_handle);
133
134         /* Wait for the reset to complete.  This prevents any races in testing
135          * where we'd immediately try to send traffic again */
136        while (kgnilnd_data.kgn_needs_reset != 0) {
137                i++;
138                LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
139                                "Waiting for stack reset request to clear\n");
140                cfs_pause(cfs_time_seconds(1 * i));
141        }
142
143         RETURN(rc);
144 }
145
146 static int LL_PROC_PROTO(proc_toggle_rdmaq_override)
147 {
148         int  old_val = kgnilnd_sysctl.ksd_rdmaq_override;
149         int  rc = 0;
150         ENTRY;
151
152         rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
153         if (!write) {
154                 /* read */
155                 RETURN(rc);
156         }
157
158         if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
159                 rc = -EINVAL;
160                 RETURN(rc);
161         }
162
163         if (old_val != kgnilnd_sysctl.ksd_rdmaq_override) {
164                 long    new_mb = kgnilnd_sysctl.ksd_rdmaq_override * (long)(1024*1024);
165                 LCONSOLE_INFO("changing RDMAQ override to %d mbytes/sec\n",
166                               kgnilnd_sysctl.ksd_rdmaq_override);
167                 /* override proc is mbytes, but we calc in bytes */
168                 kgnilnd_data.kgn_rdmaq_override = new_mb;
169                 smp_wmb();
170         }
171
172         RETURN(rc);
173 }
174
175 static cfs_sysctl_table_t kgnilnd_table[] = {
176         /*
177          * NB No .strategy entries have been provided since sysctl(8) prefers
178          * to go via /proc for portability.
179          */
180         {
181                 INIT_CTL_NAME(GNILND_VERSION)
182                 .procname = "version",
183                 .data     = KGNILND_BUILD_REV,
184                 .maxlen   = sizeof(KGNILND_BUILD_REV),
185                 .mode     = 0444,
186                 .proc_handler = &proc_dostring
187         },
188         {
189                 INIT_CTL_NAME(GNILND_THREAD_PAUSE)
190                 .procname = "thread_pause",
191                 .data     = &kgnilnd_sysctl.ksd_pause_trigger,
192                 .maxlen   = sizeof(int),
193                 .mode     = 0644,
194                 .proc_handler = &proc_toggle_thread_pause,
195         },
196         {
197                 INIT_CTL_NAME(GNILND_HW_QUIESCE)
198                 .procname = "hw_quiesce",
199                 .data     = &kgnilnd_sysctl.ksd_quiesce_secs,
200                 .maxlen   = sizeof(__u32),
201                 .mode     = 0644,
202                 .proc_handler = &proc_hw_quiesce,
203         },
204         {
205                 INIT_CTL_NAME(GNILND_STACK_RESET)
206                 .procname = "stack_reset",
207                 .data     = NULL,
208                 .maxlen   = sizeof(int),
209                 .mode     = 0600,
210                 .proc_handler = &proc_trigger_stack_reset,
211         },
212         {
213                 INIT_CTL_NAME(GNILND_RDMAQ_OVERRIDE)
214                 .procname = "rdmaq_override",
215                 .data     = &kgnilnd_sysctl.ksd_rdmaq_override,
216                 .maxlen   = sizeof(int),
217                 .mode     = 0644,
218                 .proc_handler = &proc_toggle_rdmaq_override,
219         },
220         {       INIT_CTL_NAME(0)   }
221 };
222
223 static cfs_sysctl_table_t kgnilnd_top_table[2] = {
224         {
225                 INIT_CTL_NAME(CTL_GNILND)
226                 .procname = "kgnilnd",
227                 .data     = NULL,
228                 .maxlen   = 0,
229                 .mode     = 0555,
230                 .child    = kgnilnd_table
231         },
232         {       INIT_CTL_NAME(0)   }
233 };
234
235 void kgnilnd_insert_sysctl(void)
236 {
237         if (kgnilnd_table_header == NULL)
238                 kgnilnd_table_header = cfs_register_sysctl_table(kgnilnd_top_table, 0);
239 }
240
241 void kgnilnd_remove_sysctl(void)
242 {
243         if (kgnilnd_table_header != NULL)
244                 cfs_unregister_sysctl_table(kgnilnd_table_header);
245
246         kgnilnd_table_header = NULL;
247 }
248
249 #else
250 void kgnilnd_insert_sysctl(void) {}
251 void kgnilnd_remove_sysctl(void) {}
252 #endif