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
31 #define GNILND_PEERSTATE_STRLEN 16
32 typedef struct kgn_sysctl_data {
33 int ksd_pause_trigger;
35 int ksd_rdmaq_override;
36 char ksd_peer_state[GNILND_PEERSTATE_STRLEN];
39 static kgn_sysctl_data_t kgnilnd_sysctl;
41 #if defined(CONFIG_SYSCTL)
43 static struct ctl_table_header *kgnilnd_table_header = NULL;
46 proc_toggle_thread_pause(struct ctl_table *table, int write,
47 void __user *buffer, size_t *lenp, loff_t *ppos)
49 int old_val = kgnilnd_sysctl.ksd_pause_trigger;
53 rc = proc_dointvec(table, write, buffer, lenp, ppos);
59 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
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);
76 proc_hw_quiesce(struct ctl_table *table, int write, void __user *buffer,
77 size_t *lenp, loff_t *ppos)
83 rc = proc_dointvec(table, write, buffer, lenp, ppos);
89 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
95 /* only device 0 gets the handle, see kgnilnd_dev_init */
96 dev = &kgnilnd_data.kgn_devices[0];
98 LASSERTF(dev != NULL, "dev 0 is NULL\n");
100 kgnilnd_quiesce_end_callback(dev->gnd_handle,
101 kgnilnd_sysctl.ksd_quiesce_secs * MSEC_PER_SEC);
107 proc_trigger_stack_reset(struct ctl_table *table, int write,
108 void __user *buffer, size_t *lenp, loff_t *ppos)
117 rc = proc_dointvec(table, write, buffer, lenp, ppos);
121 /* only device 0 gets the handle, see kgnilnd_dev_init */
122 dev = &kgnilnd_data.kgn_devices[0];
124 LASSERTF(dev != NULL, "dev 0 is NULL\n");
126 kgnilnd_critical_error(dev->gnd_err_handle);
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) {
132 LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
133 "Waiting for stack reset request to clear\n");
134 set_current_state(TASK_UNINTERRUPTIBLE);
135 schedule_timeout(cfs_time_seconds(1 * i));
142 proc_toggle_rdmaq_override(struct ctl_table *table, int write,
143 void __user *buffer, size_t *lenp, loff_t *ppos)
145 int old_val = kgnilnd_sysctl.ksd_rdmaq_override;
149 rc = proc_dointvec(table, write, buffer, lenp, ppos);
155 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
160 if (old_val != kgnilnd_sysctl.ksd_rdmaq_override) {
161 long new_mb = kgnilnd_sysctl.ksd_rdmaq_override * (long)(1024*1024);
162 LCONSOLE_INFO("changing RDMAQ override to %d mbytes/sec\n",
163 kgnilnd_sysctl.ksd_rdmaq_override);
164 /* override proc is mbytes, but we calc in bytes */
165 kgnilnd_data.kgn_rdmaq_override = new_mb;
172 /* /proc/sys entry point for injecting up/down nid event
176 proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
177 size_t *lenp, loff_t *ppos)
185 rc = proc_dostring(table, write, buffer, lenp, ppos);
192 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
197 /* convert to nid, up/down values */
198 rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
199 CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);
202 CDEBUG(D_ERROR, "invalid parameter\n");
205 switch (command[0]) {
208 CDEBUG(D_INFO, "take node %d down\n", nid);
212 CDEBUG(D_INFO, "bring node %d up\n", nid);
215 CDEBUG(D_ERROR, "invalid command %s\n", command);
220 CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
222 rc = kgnilnd_report_node_state(nid, node_down);
231 static struct ctl_table kgnilnd_table[] = {
233 * NB No .strategy entries have been provided since sysctl(8) prefers
234 * to go via /proc for portability.
238 .procname = "version",
239 .data = KGNILND_BUILD_REV,
240 .maxlen = sizeof(KGNILND_BUILD_REV),
242 .proc_handler = &proc_dostring
246 .procname = "thread_pause",
247 .data = &kgnilnd_sysctl.ksd_pause_trigger,
248 .maxlen = sizeof(int),
250 .proc_handler = &proc_toggle_thread_pause,
254 .procname = "hw_quiesce",
255 .data = &kgnilnd_sysctl.ksd_quiesce_secs,
256 .maxlen = sizeof(__u32),
258 .proc_handler = &proc_hw_quiesce,
262 .procname = "stack_reset",
264 .maxlen = sizeof(int),
266 .proc_handler = &proc_trigger_stack_reset,
270 .procname = "rdmaq_override",
271 .data = &kgnilnd_sysctl.ksd_rdmaq_override,
272 .maxlen = sizeof(int),
274 .proc_handler = &proc_toggle_rdmaq_override,
278 .procname = "peer_state",
279 .data = kgnilnd_sysctl.ksd_peer_state,
280 .maxlen = GNILND_PEERSTATE_STRLEN,
282 .proc_handler = &proc_peer_state,
287 static struct ctl_table kgnilnd_top_table[2] = {
290 .procname = "kgnilnd",
294 .child = kgnilnd_table
299 void kgnilnd_insert_sysctl(void)
301 if (kgnilnd_table_header == NULL)
302 kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
305 void kgnilnd_remove_sysctl(void)
307 if (kgnilnd_table_header != NULL)
308 unregister_sysctl_table(kgnilnd_table_header);
310 kgnilnd_table_header = NULL;
314 void kgnilnd_insert_sysctl(void) {}
315 void kgnilnd_remove_sysctl(void) {}