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 schedule_timeout_uninterruptible(cfs_time_seconds(i));
143 proc_toggle_rdmaq_override(struct ctl_table *table, int write,
144 void __user *buffer, size_t *lenp, loff_t *ppos)
146 int old_val = kgnilnd_sysctl.ksd_rdmaq_override;
150 rc = proc_dointvec(table, write, buffer, lenp, ppos);
156 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
161 if (old_val != kgnilnd_sysctl.ksd_rdmaq_override) {
162 long new_mb = kgnilnd_sysctl.ksd_rdmaq_override * (long)(1024*1024);
163 LCONSOLE_INFO("changing RDMAQ override to %d mbytes/sec\n",
164 kgnilnd_sysctl.ksd_rdmaq_override);
165 /* override proc is mbytes, but we calc in bytes */
166 kgnilnd_data.kgn_rdmaq_override = new_mb;
173 /* /proc/sys entry point for injecting up/down nid event
177 proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
178 size_t *lenp, loff_t *ppos)
186 rc = proc_dostring(table, write, buffer, lenp, ppos);
193 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
198 /* convert to nid, up/down values */
199 rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
200 CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);
203 CDEBUG(D_ERROR, "invalid parameter\n");
206 switch (command[0]) {
209 CDEBUG(D_INFO, "take node %d down\n", nid);
213 CDEBUG(D_INFO, "bring node %d up\n", nid);
216 CDEBUG(D_ERROR, "invalid command %s\n", command);
221 CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
223 rc = kgnilnd_report_node_state(nid, node_down);
232 static struct ctl_table kgnilnd_table[] = {
234 * NB No .strategy entries have been provided since sysctl(8) prefers
235 * to go via /proc for portability.
238 .procname = "version",
239 .data = LUSTRE_VERSION_STRING,
240 .maxlen = sizeof(LUSTRE_VERSION_STRING),
242 .proc_handler = &proc_dostring
245 .procname = "thread_pause",
246 .data = &kgnilnd_sysctl.ksd_pause_trigger,
247 .maxlen = sizeof(int),
249 .proc_handler = &proc_toggle_thread_pause,
252 .procname = "hw_quiesce",
253 .data = &kgnilnd_sysctl.ksd_quiesce_secs,
254 .maxlen = sizeof(__u32),
256 .proc_handler = &proc_hw_quiesce,
259 .procname = "stack_reset",
261 .maxlen = sizeof(int),
263 .proc_handler = &proc_trigger_stack_reset,
266 .procname = "rdmaq_override",
267 .data = &kgnilnd_sysctl.ksd_rdmaq_override,
268 .maxlen = sizeof(int),
270 .proc_handler = &proc_toggle_rdmaq_override,
273 .procname = "peer_state",
274 .data = kgnilnd_sysctl.ksd_peer_state,
275 .maxlen = GNILND_PEERSTATE_STRLEN,
277 .proc_handler = &proc_peer_state,
282 static struct ctl_table kgnilnd_top_table[2] = {
284 .procname = "kgnilnd",
288 .child = kgnilnd_table
293 void kgnilnd_insert_sysctl(void)
295 if (kgnilnd_table_header == NULL)
296 kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
299 void kgnilnd_remove_sysctl(void)
301 if (kgnilnd_table_header != NULL)
302 unregister_sysctl_table(kgnilnd_table_header);
304 kgnilnd_table_header = NULL;
308 void kgnilnd_insert_sysctl(void) {}
309 void kgnilnd_remove_sysctl(void) {}