2 * Copyright (C) 2012 Cray, Inc.
4 * Author: Nic Henke <nic@cray.com>
5 * Author: James Shimek <jshimek@cray.com>
7 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
23 /* this code liberated and modified from Lustre */
25 #define DEBUG_SUBSYSTEM S_LND
29 #define GNILND_PEERSTATE_STRLEN 16
30 typedef struct kgn_sysctl_data {
31 int ksd_pause_trigger;
33 int ksd_rdmaq_override;
34 char ksd_peer_state[GNILND_PEERSTATE_STRLEN];
37 static kgn_sysctl_data_t kgnilnd_sysctl;
39 #if defined(CONFIG_SYSCTL)
41 static struct ctl_table_header *kgnilnd_table_header = NULL;
44 proc_toggle_thread_pause(struct ctl_table *table, int write,
45 void __user *buffer, size_t *lenp, loff_t *ppos)
47 int old_val = kgnilnd_sysctl.ksd_pause_trigger;
51 rc = proc_dointvec(table, write, buffer, lenp, ppos);
57 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
62 if (old_val != kgnilnd_sysctl.ksd_pause_trigger) {
63 mutex_lock(&kgnilnd_data.kgn_quiesce_mutex);
64 CDEBUG(D_NET, "setting quiesce_trigger %d\n", old_val);
65 kgnilnd_data.kgn_quiesce_trigger = kgnilnd_sysctl.ksd_pause_trigger;
66 kgnilnd_quiesce_wait("admin sysctl");
67 mutex_unlock(&kgnilnd_data.kgn_quiesce_mutex);
74 proc_hw_quiesce(struct ctl_table *table, int write, void __user *buffer,
75 size_t *lenp, loff_t *ppos)
81 rc = proc_dointvec(table, write, buffer, lenp, ppos);
87 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
93 /* only device 0 gets the handle, see kgnilnd_dev_init */
94 dev = &kgnilnd_data.kgn_devices[0];
96 LASSERTF(dev != NULL, "dev 0 is NULL\n");
98 kgnilnd_quiesce_end_callback(dev->gnd_handle,
99 kgnilnd_sysctl.ksd_quiesce_secs * MSEC_PER_SEC);
105 proc_trigger_stack_reset(struct ctl_table *table, int write,
106 void __user *buffer, size_t *lenp, loff_t *ppos)
115 rc = proc_dointvec(table, write, buffer, lenp, ppos);
119 /* only device 0 gets the handle, see kgnilnd_dev_init */
120 dev = &kgnilnd_data.kgn_devices[0];
122 LASSERTF(dev != NULL, "dev 0 is NULL\n");
124 kgnilnd_critical_error(dev->gnd_err_handle);
126 /* Wait for the reset to complete. This prevents any races in testing
127 * where we'd immediately try to send traffic again */
128 while (kgnilnd_data.kgn_needs_reset != 0) {
130 LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
131 "Waiting for stack reset request to clear\n");
132 cfs_pause(cfs_time_seconds(1 * i));
139 proc_toggle_rdmaq_override(struct ctl_table *table, int write,
140 void __user *buffer, size_t *lenp, loff_t *ppos)
142 int old_val = kgnilnd_sysctl.ksd_rdmaq_override;
146 rc = proc_dointvec(table, write, buffer, lenp, ppos);
152 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
157 if (old_val != kgnilnd_sysctl.ksd_rdmaq_override) {
158 long new_mb = kgnilnd_sysctl.ksd_rdmaq_override * (long)(1024*1024);
159 LCONSOLE_INFO("changing RDMAQ override to %d mbytes/sec\n",
160 kgnilnd_sysctl.ksd_rdmaq_override);
161 /* override proc is mbytes, but we calc in bytes */
162 kgnilnd_data.kgn_rdmaq_override = new_mb;
169 /* /proc/sys entry point for injecting up/down nid event
173 proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
174 size_t *lenp, loff_t *ppos)
182 rc = proc_dostring(table, write, buffer, lenp, ppos);
189 if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
194 /* convert to nid, up/down values */
195 rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
196 CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);
199 CDEBUG(D_ERROR, "invalid parameter\n");
202 switch (command[0]) {
205 CDEBUG(D_INFO, "take node %d down\n", nid);
209 CDEBUG(D_INFO, "bring node %d up\n", nid);
212 CDEBUG(D_ERROR, "invalid command %s\n", command);
217 CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
219 rc = kgnilnd_report_node_state(nid, node_down);
228 static struct ctl_table kgnilnd_table[] = {
230 * NB No .strategy entries have been provided since sysctl(8) prefers
231 * to go via /proc for portability.
235 .procname = "version",
236 .data = KGNILND_BUILD_REV,
237 .maxlen = sizeof(KGNILND_BUILD_REV),
239 .proc_handler = &proc_dostring
243 .procname = "thread_pause",
244 .data = &kgnilnd_sysctl.ksd_pause_trigger,
245 .maxlen = sizeof(int),
247 .proc_handler = &proc_toggle_thread_pause,
251 .procname = "hw_quiesce",
252 .data = &kgnilnd_sysctl.ksd_quiesce_secs,
253 .maxlen = sizeof(__u32),
255 .proc_handler = &proc_hw_quiesce,
259 .procname = "stack_reset",
261 .maxlen = sizeof(int),
263 .proc_handler = &proc_trigger_stack_reset,
267 .procname = "rdmaq_override",
268 .data = &kgnilnd_sysctl.ksd_rdmaq_override,
269 .maxlen = sizeof(int),
271 .proc_handler = &proc_toggle_rdmaq_override,
275 .procname = "peer_state",
276 .data = kgnilnd_sysctl.ksd_peer_state,
277 .maxlen = GNILND_PEERSTATE_STRLEN,
279 .proc_handler = &proc_peer_state,
284 static struct ctl_table kgnilnd_top_table[2] = {
287 .procname = "kgnilnd",
291 .child = kgnilnd_table
296 void kgnilnd_insert_sysctl(void)
298 if (kgnilnd_table_header == NULL)
299 kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
302 void kgnilnd_remove_sysctl(void)
304 if (kgnilnd_table_header != NULL)
305 unregister_sysctl_table(kgnilnd_table_header);
307 kgnilnd_table_header = NULL;
311 void kgnilnd_insert_sysctl(void) {}
312 void kgnilnd_remove_sysctl(void) {}