Whamcloud - gitweb
LU-6261 gnilnd: Add pkey module parameter
[fs/lustre-release.git] / lnet / klnds / gnilnd / gnilnd_sysctl.c
index cd33d3e..aae29d5 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Copyright (C) 2012 Cray, Inc.
  *
+ * Copyright (c) 2014, Intel Corporation.
+ *
  *   Author: Nic Henke <nic@cray.com>
  *   Author: James Shimek <jshimek@cray.com>
  *
 
 #include "gnilnd.h"
 
+#define GNILND_PEERSTATE_STRLEN 16
 typedef struct kgn_sysctl_data {
        int                     ksd_pause_trigger;
        int                     ksd_quiesce_secs;
        int                     ksd_rdmaq_override;
+       char                    ksd_peer_state[GNILND_PEERSTATE_STRLEN];
 } kgn_sysctl_data_t;
 
 static kgn_sysctl_data_t        kgnilnd_sysctl;
 
 #if defined(CONFIG_SYSCTL)
 
-static cfs_sysctl_table_header_t *kgnilnd_table_header = NULL;
-#ifndef HAVE_SYSCTL_UNNUMBERED
-
-enum {
-       GNILND_VERSION = 1,
-       GNILND_THREAD_PAUSE,
-       GNILND_HW_QUIESCE,
-       GNILND_STACK_RESET,
-       GNILND_RDMAQ_OVERRIDE,
-};
-#else
-#define GNILND_VERSION             CTL_UNNUMBERED
-#define GNILND_THREAD_PAUSE        CTL_UNNUMBERED
-#define GNILND_HW_QUIESCE          CTL_UNNUMBERED
-#define GNILND_STACK_RESET         CTL_UNNUMBERED
-#define GNILND_RDMAQ_OVERRIDE      CTL_UNNUMBERED
-#endif
+static struct ctl_table_header *kgnilnd_table_header = NULL;
 
-static int LL_PROC_PROTO(proc_toggle_thread_pause)
+static int
+proc_toggle_thread_pause(struct ctl_table *table, int write,
+                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int  old_val = kgnilnd_sysctl.ksd_pause_trigger;
        int  rc = 0;
        ENTRY;
 
-       rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
+       rc = proc_dointvec(table, write, buffer, lenp, ppos);
        if (!write) {
                /* read */
                RETURN(rc);
@@ -72,23 +62,25 @@ static int LL_PROC_PROTO(proc_toggle_thread_pause)
        }
 
        if (old_val != kgnilnd_sysctl.ksd_pause_trigger) {
-               down(&kgnilnd_data.kgn_quiesce_sem);
+               mutex_lock(&kgnilnd_data.kgn_quiesce_mutex);
                CDEBUG(D_NET, "setting quiesce_trigger %d\n", old_val);
                kgnilnd_data.kgn_quiesce_trigger = kgnilnd_sysctl.ksd_pause_trigger;
                kgnilnd_quiesce_wait("admin sysctl");
-               up(&kgnilnd_data.kgn_quiesce_sem);
+               mutex_unlock(&kgnilnd_data.kgn_quiesce_mutex);
        }
 
        RETURN(rc);
 }
 
-static int LL_PROC_PROTO(proc_hw_quiesce)
+static int
+proc_hw_quiesce(struct ctl_table *table, int write, void __user *buffer,
+               size_t *lenp, loff_t *ppos)
 {
        int              rc = 0;
        kgn_device_t    *dev;
        ENTRY;
 
-       rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
+       rc = proc_dointvec(table, write, buffer, lenp, ppos);
        if (!write) {
                /* read */
                RETURN(rc);
@@ -111,16 +103,18 @@ static int LL_PROC_PROTO(proc_hw_quiesce)
        RETURN(rc);
 }
 
-int LL_PROC_PROTO(proc_trigger_stack_reset)
+static int
+proc_trigger_stack_reset(struct ctl_table *table, int write,
+                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int              rc = 0;
-       int                i = 1;
-       kgn_device_t    *dev;
+       int              i = 1;
+       kgn_device_t    *dev;
        ENTRY;
 
        if (!write) {
                /* read */
-               rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
+               rc = proc_dointvec(table, write, buffer, lenp, ppos);
                RETURN(rc);
        }
 
@@ -133,23 +127,26 @@ int LL_PROC_PROTO(proc_trigger_stack_reset)
 
        /* Wait for the reset to complete.  This prevents any races in testing
         * where we'd immediately try to send traffic again */
-       while (kgnilnd_data.kgn_needs_reset != 0) {
-              i++;
-              LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
-                              "Waiting for stack reset request to clear\n");
-              cfs_pause(cfs_time_seconds(1 * i));
-       }
+       while (kgnilnd_data.kgn_needs_reset != 0) {
+               i++;
+               LCONSOLE((((i) & (-i)) == i) ? D_WARNING : D_NET,
+                               "Waiting for stack reset request to clear\n");
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(cfs_time_seconds(1 * i));
+       }
 
        RETURN(rc);
 }
 
-static int LL_PROC_PROTO(proc_toggle_rdmaq_override)
+static int
+proc_toggle_rdmaq_override(struct ctl_table *table, int write,
+                          void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int  old_val = kgnilnd_sysctl.ksd_rdmaq_override;
        int  rc = 0;
        ENTRY;
 
-       rc = ll_proc_dointvec(table, write, filp, buffer, lenp, ppos);
+       rc = proc_dointvec(table, write, buffer, lenp, ppos);
        if (!write) {
                /* read */
                RETURN(rc);
@@ -172,13 +169,72 @@ static int LL_PROC_PROTO(proc_toggle_rdmaq_override)
        RETURN(rc);
 }
 
-static cfs_sysctl_table_t kgnilnd_table[] = {
+/* /proc/sys entry point for injecting up/down nid event
+ * <up|down> <nid>
+ */
+static int
+proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
+               size_t *lenp, loff_t *ppos)
+{
+       int             rc;
+       int             nid;
+       int             node_down;
+       char            command[10];
+       ENTRY;
+
+       rc = proc_dostring(table, write, buffer, lenp, ppos);
+
+       if (!write) {
+               /* read */
+               RETURN(rc);
+       }
+
+       if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
+               rc = -EINVAL;
+               RETURN(rc);
+       }
+
+       /* convert to nid, up/down values */
+       rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
+       CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);
+
+       if (rc != 2) {
+               CDEBUG(D_ERROR, "invalid parameter\n");
+               RETURN(rc);
+       } else {
+               switch (command[0]) {
+               case 'd': /* down */
+                       node_down = 1;
+                       CDEBUG(D_INFO, "take node %d down\n", nid);
+                       break;
+               case 'u': /* up */
+                       node_down = 0;
+                       CDEBUG(D_INFO, "bring node %d up\n", nid);
+                       break;
+               default:
+                       CDEBUG(D_ERROR, "invalid command %s\n", command);
+                       RETURN(-EINVAL);
+               }
+       }
+
+       CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
+                     node_down, nid);
+       rc = kgnilnd_report_node_state(nid, node_down);
+
+       if (rc) {
+               rc = -EINVAL;
+       }
+
+       RETURN(rc);
+}
+
+static struct ctl_table kgnilnd_table[] = {
        /*
         * NB No .strategy entries have been provided since sysctl(8) prefers
         * to go via /proc for portability.
         */
        {
-               INIT_CTL_NAME(GNILND_VERSION)
+               INIT_CTL_NAME
                .procname = "version",
                .data     = KGNILND_BUILD_REV,
                .maxlen   = sizeof(KGNILND_BUILD_REV),
@@ -186,7 +242,7 @@ static cfs_sysctl_table_t kgnilnd_table[] = {
                .proc_handler = &proc_dostring
        },
        {
-               INIT_CTL_NAME(GNILND_THREAD_PAUSE)
+               INIT_CTL_NAME
                .procname = "thread_pause",
                .data     = &kgnilnd_sysctl.ksd_pause_trigger,
                .maxlen   = sizeof(int),
@@ -194,7 +250,7 @@ static cfs_sysctl_table_t kgnilnd_table[] = {
                .proc_handler = &proc_toggle_thread_pause,
        },
        {
-               INIT_CTL_NAME(GNILND_HW_QUIESCE)
+               INIT_CTL_NAME
                .procname = "hw_quiesce",
                .data     = &kgnilnd_sysctl.ksd_quiesce_secs,
                .maxlen   = sizeof(__u32),
@@ -202,7 +258,7 @@ static cfs_sysctl_table_t kgnilnd_table[] = {
                .proc_handler = &proc_hw_quiesce,
        },
        {
-               INIT_CTL_NAME(GNILND_STACK_RESET)
+               INIT_CTL_NAME
                .procname = "stack_reset",
                .data     = NULL,
                .maxlen   = sizeof(int),
@@ -210,38 +266,46 @@ static cfs_sysctl_table_t kgnilnd_table[] = {
                .proc_handler = &proc_trigger_stack_reset,
        },
        {
-               INIT_CTL_NAME(GNILND_RDMAQ_OVERRIDE)
+               INIT_CTL_NAME
                .procname = "rdmaq_override",
                .data     = &kgnilnd_sysctl.ksd_rdmaq_override,
                .maxlen   = sizeof(int),
                .mode     = 0644,
                .proc_handler = &proc_toggle_rdmaq_override,
        },
-       {       INIT_CTL_NAME(0)   }
+       {
+               INIT_CTL_NAME
+               .procname = "peer_state",
+               .data     = kgnilnd_sysctl.ksd_peer_state,
+               .maxlen   = GNILND_PEERSTATE_STRLEN,
+               .mode     = 0644,
+               .proc_handler = &proc_peer_state,
+       },
+       { 0 }
 };
 
-static cfs_sysctl_table_t kgnilnd_top_table[2] = {
+static struct ctl_table kgnilnd_top_table[2] = {
        {
-               INIT_CTL_NAME(CTL_GNILND)
+               INIT_CTL_NAME
                .procname = "kgnilnd",
                .data     = NULL,
                .maxlen   = 0,
                .mode     = 0555,
                .child    = kgnilnd_table
        },
-       {       INIT_CTL_NAME(0)   }
+       { 0 }
 };
 
 void kgnilnd_insert_sysctl(void)
 {
        if (kgnilnd_table_header == NULL)
-               kgnilnd_table_header = cfs_register_sysctl_table(kgnilnd_top_table, 0);
+               kgnilnd_table_header = register_sysctl_table(kgnilnd_top_table);
 }
 
 void kgnilnd_remove_sysctl(void)
 {
        if (kgnilnd_table_header != NULL)
-               cfs_unregister_sysctl_table(kgnilnd_table_header);
+               unregister_sysctl_table(kgnilnd_table_header);
 
        kgnilnd_table_header = NULL;
 }