2 * Copyright (C) 2012 Cray, Inc.
4 * Copyright (c) 2014, Intel Corporation.
6 * Author: Nic Henke <nic@cray.com>
7 * Author: James Shimek <jshimek@cray.com>
9 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
25 /* this code liberated and modified from Lustre */
27 #define DEBUG_SUBSYSTEM S_LND
29 #include <libcfs/linux/linux-misc.h>
33 #define GNILND_PEERSTATE_STRLEN 16
34 typedef struct kgn_sysctl_data {
35 int ksd_pause_trigger;
37 int ksd_rdmaq_override;
38 char ksd_peer_state[GNILND_PEERSTATE_STRLEN];
41 static kgn_sysctl_data_t kgnilnd_sysctl;
43 #if defined(CONFIG_SYSCTL)
45 static struct ctl_table_header *kgnilnd_table_header = NULL;
48 proc_toggle_thread_pause(struct ctl_table *table, int write,
49 void __user *buffer, size_t *lenp, loff_t *ppos)
51 int old_val = kgnilnd_sysctl.ksd_pause_trigger;
55 rc = proc_dointvec(table, write, buffer, lenp, ppos);
61 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
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);
78 proc_hw_quiesce(struct ctl_table *table, int write, void __user *buffer,
79 size_t *lenp, loff_t *ppos)
85 rc = proc_dointvec(table, write, buffer, lenp, ppos);
91 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
97 /* only device 0 gets the handle, see kgnilnd_dev_init */
98 dev = &kgnilnd_data.kgn_devices[0];
100 LASSERTF(dev != NULL, "dev 0 is NULL\n");
102 kgnilnd_quiesce_end_callback(dev->gnd_handle,
103 kgnilnd_sysctl.ksd_quiesce_secs * MSEC_PER_SEC);
109 proc_trigger_stack_reset(struct ctl_table *table, int write,
110 void __user *buffer, size_t *lenp, loff_t *ppos)
119 rc = proc_dointvec(table, write, buffer, lenp, ppos);
123 /* only device 0 gets the handle, see kgnilnd_dev_init */
124 dev = &kgnilnd_data.kgn_devices[0];
126 LASSERTF(dev != NULL, "dev 0 is NULL\n");
128 kgnilnd_critical_error(dev->gnd_err_handle);
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) {
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));
144 proc_toggle_rdmaq_override(struct ctl_table *table, int write,
145 void __user *buffer, size_t *lenp, loff_t *ppos)
147 int old_val = kgnilnd_sysctl.ksd_rdmaq_override;
151 rc = proc_dointvec(table, write, buffer, lenp, ppos);
157 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
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;
174 /* /proc/sys entry point for injecting up/down nid event
178 proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
179 size_t *lenp, loff_t *ppos)
187 rc = proc_dostring(table, write, buffer, lenp, ppos);
194 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
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);
204 CDEBUG(D_ERROR, "invalid parameter\n");
207 switch (command[0]) {
210 CDEBUG(D_INFO, "take node %d down\n", nid);
214 CDEBUG(D_INFO, "bring node %d up\n", nid);
217 CDEBUG(D_ERROR, "invalid command %s\n", command);
222 CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
224 rc = kgnilnd_report_node_state(nid, node_down);
233 static struct ctl_table kgnilnd_table[] = {
235 * NB No .strategy entries have been provided since sysctl(8) prefers
236 * to go via /proc for portability.
240 .procname = "version",
241 .data = LUSTRE_VERSION_STRING,
242 .maxlen = sizeof(LUSTRE_VERSION_STRING),
244 .proc_handler = &proc_dostring
248 .procname = "thread_pause",
249 .data = &kgnilnd_sysctl.ksd_pause_trigger,
250 .maxlen = sizeof(int),
252 .proc_handler = &proc_toggle_thread_pause,
256 .procname = "hw_quiesce",
257 .data = &kgnilnd_sysctl.ksd_quiesce_secs,
258 .maxlen = sizeof(__u32),
260 .proc_handler = &proc_hw_quiesce,
264 .procname = "stack_reset",
266 .maxlen = sizeof(int),
268 .proc_handler = &proc_trigger_stack_reset,
272 .procname = "rdmaq_override",
273 .data = &kgnilnd_sysctl.ksd_rdmaq_override,
274 .maxlen = sizeof(int),
276 .proc_handler = &proc_toggle_rdmaq_override,
280 .procname = "peer_state",
281 .data = kgnilnd_sysctl.ksd_peer_state,
282 .maxlen = GNILND_PEERSTATE_STRLEN,
284 .proc_handler = &proc_peer_state,
289 static struct ctl_table kgnilnd_top_table[2] = {
292 .procname = "kgnilnd",
296 .child = kgnilnd_table
301 void kgnilnd_insert_sysctl(void)
303 if (kgnilnd_table_header == NULL)
304 kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
307 void kgnilnd_remove_sysctl(void)
309 if (kgnilnd_table_header != NULL)
310 unregister_sysctl_table(kgnilnd_table_header);
312 kgnilnd_table_header = NULL;
316 void kgnilnd_insert_sysctl(void) {}
317 void kgnilnd_remove_sysctl(void) {}