Whamcloud - gitweb
LU-12930 various: use schedule_timeout_*interruptible
[fs/lustre-release.git] / lnet / lnet / api-ni.c
index 07558df..d39e6b9 100644 (file)
@@ -80,10 +80,10 @@ MODULE_PARM_DESC(lnet_numa_range,
 
 /*
  * lnet_health_sensitivity determines by how much we decrement the health
- * value on sending error. The value defaults to 0, which means health
- * checking is turned off by default.
+ * value on sending error. The value defaults to 100, which means health
+ * interface health is decremented by 100 points every failure.
  */
-unsigned int lnet_health_sensitivity = 0;
+unsigned int lnet_health_sensitivity = 100;
 static int sensitivity_set(const char *val, cfs_kernel_param_arg_t *kp);
 #ifdef HAVE_KERNEL_PARAM_OPS
 static struct kernel_param_ops param_ops_health_sensitivity = {
@@ -179,7 +179,10 @@ module_param_call(lnet_drop_asym_route, drop_asym_route_set, param_get_int,
 MODULE_PARM_DESC(lnet_drop_asym_route,
                 "Set to 1 to drop asymmetrical route messages.");
 
-unsigned lnet_transaction_timeout = 50;
+#define LNET_TRANSACTION_TIMEOUT_NO_HEALTH_DEFAULT 50
+#define LNET_TRANSACTION_TIMEOUT_HEALTH_DEFAULT 50
+
+unsigned lnet_transaction_timeout = LNET_TRANSACTION_TIMEOUT_HEALTH_DEFAULT;
 static int transaction_to_set(const char *val, cfs_kernel_param_arg_t *kp);
 #ifdef HAVE_KERNEL_PARAM_OPS
 static struct kernel_param_ops param_ops_transaction_timeout = {
@@ -197,7 +200,8 @@ module_param_call(lnet_transaction_timeout, transaction_to_set, param_get_int,
 MODULE_PARM_DESC(lnet_transaction_timeout,
                "Maximum number of seconds to wait for a peer response.");
 
-unsigned lnet_retry_count = 0;
+#define LNET_RETRY_COUNT_HEALTH_DEFAULT 2
+unsigned lnet_retry_count = LNET_RETRY_COUNT_HEALTH_DEFAULT;
 static int retry_count_set(const char *val, cfs_kernel_param_arg_t *kp);
 #ifdef HAVE_KERNEL_PARAM_OPS
 static struct kernel_param_ops param_ops_retry_count = {
@@ -217,6 +221,7 @@ MODULE_PARM_DESC(lnet_retry_count,
 
 
 unsigned lnet_lnd_timeout = LNET_LND_DEFAULT_TIMEOUT;
+unsigned int lnet_current_net_count;
 
 /*
  * This sequence number keeps track of how many times DLC was used to
@@ -252,11 +257,6 @@ sensitivity_set(const char *val, cfs_kernel_param_arg_t *kp)
         */
        mutex_lock(&the_lnet.ln_api_mutex);
 
-       if (the_lnet.ln_state != LNET_STATE_RUNNING) {
-               mutex_unlock(&the_lnet.ln_api_mutex);
-               return 0;
-       }
-
        if (value > LNET_MAX_HEALTH_VALUE) {
                mutex_unlock(&the_lnet.ln_api_mutex);
                CERROR("Invalid health value. Maximum: %d value = %lu\n",
@@ -264,6 +264,23 @@ sensitivity_set(const char *val, cfs_kernel_param_arg_t *kp)
                return -EINVAL;
        }
 
+       /*
+        * if we're turning on health then use the health timeout
+        * defaults.
+        */
+       if (*sensitivity == 0 && value != 0) {
+               lnet_transaction_timeout = LNET_TRANSACTION_TIMEOUT_HEALTH_DEFAULT;
+               lnet_retry_count = LNET_RETRY_COUNT_HEALTH_DEFAULT;
+       /*
+        * if we're turning off health then use the no health timeout
+        * default.
+        */
+       } else if (*sensitivity != 0 && value == 0) {
+               lnet_transaction_timeout =
+                       LNET_TRANSACTION_TIMEOUT_NO_HEALTH_DEFAULT;
+               lnet_retry_count = 0;
+       }
+
        *sensitivity = value;
 
        mutex_unlock(&the_lnet.ln_api_mutex);
@@ -295,11 +312,6 @@ recovery_interval_set(const char *val, cfs_kernel_param_arg_t *kp)
         */
        mutex_lock(&the_lnet.ln_api_mutex);
 
-       if (the_lnet.ln_state != LNET_STATE_RUNNING) {
-               mutex_unlock(&the_lnet.ln_api_mutex);
-               return 0;
-       }
-
        *interval = value;
 
        mutex_unlock(&the_lnet.ln_api_mutex);
@@ -408,11 +420,6 @@ transaction_to_set(const char *val, cfs_kernel_param_arg_t *kp)
         */
        mutex_lock(&the_lnet.ln_api_mutex);
 
-       if (the_lnet.ln_state != LNET_STATE_RUNNING) {
-               mutex_unlock(&the_lnet.ln_api_mutex);
-               return 0;
-       }
-
        if (value < lnet_retry_count || value == 0) {
                mutex_unlock(&the_lnet.ln_api_mutex);
                CERROR("Invalid value for lnet_transaction_timeout (%lu). "
@@ -456,9 +463,10 @@ retry_count_set(const char *val, cfs_kernel_param_arg_t *kp)
         */
        mutex_lock(&the_lnet.ln_api_mutex);
 
-       if (the_lnet.ln_state != LNET_STATE_RUNNING) {
+       if (lnet_health_sensitivity == 0) {
                mutex_unlock(&the_lnet.ln_api_mutex);
-               return 0;
+               CERROR("Can not set retry_count when health feature is turned off\n");
+               return -EINVAL;
        }
 
        if (value > lnet_transaction_timeout) {
@@ -469,11 +477,6 @@ retry_count_set(const char *val, cfs_kernel_param_arg_t *kp)
                return -EINVAL;
        }
 
-       if (value == *retry_count) {
-               mutex_unlock(&the_lnet.ln_api_mutex);
-               return 0;
-       }
-
        *retry_count = value;
 
        if (value == 0)
@@ -543,21 +546,18 @@ lnet_init_locks(void)
        spin_lock_init(&the_lnet.ln_eq_wait_lock);
        spin_lock_init(&the_lnet.ln_msg_resend_lock);
        init_waitqueue_head(&the_lnet.ln_eq_waitq);
-       init_waitqueue_head(&the_lnet.ln_mt_waitq);
+       init_completion(&the_lnet.ln_mt_wait_complete);
        mutex_init(&the_lnet.ln_lnd_mutex);
 }
 
-static void
-lnet_fini_locks(void)
-{
-}
-
 struct kmem_cache *lnet_mes_cachep;       /* MEs kmem_cache */
 struct kmem_cache *lnet_small_mds_cachep;  /* <= LNET_SMALL_MD_SIZE bytes
                                            *  MDs kmem_cache */
+struct kmem_cache *lnet_rspt_cachep;      /* response tracker cache */
+struct kmem_cache *lnet_msg_cachep;
 
 static int
-lnet_descriptor_setup(void)
+lnet_slab_setup(void)
 {
        /* create specific kmem_cache for MEs and small MDs (i.e., originally
         * allocated in <size-xxx> kmem_cache).
@@ -573,12 +573,32 @@ lnet_descriptor_setup(void)
        if (!lnet_small_mds_cachep)
                return -ENOMEM;
 
+       lnet_rspt_cachep = kmem_cache_create("lnet_rspt", sizeof(struct lnet_rsp_tracker),
+                                           0, 0, NULL);
+       if (!lnet_rspt_cachep)
+               return -ENOMEM;
+
+       lnet_msg_cachep = kmem_cache_create("lnet_msg", sizeof(struct lnet_msg),
+                                           0, 0, NULL);
+       if (!lnet_msg_cachep)
+               return -ENOMEM;
+
        return 0;
 }
 
 static void
-lnet_descriptor_cleanup(void)
+lnet_slab_cleanup(void)
 {
+       if (lnet_msg_cachep) {
+               kmem_cache_destroy(lnet_msg_cachep);
+               lnet_msg_cachep = NULL;
+       }
+
+
+       if (lnet_rspt_cachep) {
+               kmem_cache_destroy(lnet_rspt_cachep);
+               lnet_rspt_cachep = NULL;
+       }
 
        if (lnet_small_mds_cachep) {
                kmem_cache_destroy(lnet_small_mds_cachep);
@@ -640,8 +660,6 @@ lnet_destroy_locks(void)
                cfs_percpt_lock_free(the_lnet.ln_net_lock);
                the_lnet.ln_net_lock = NULL;
        }
-
-       lnet_fini_locks();
 }
 
 static int
@@ -672,141 +690,142 @@ static void lnet_assert_wire_constants(void)
         * with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) */
 
        /* Constants... */
-       CLASSERT(LNET_PROTO_TCP_MAGIC == 0xeebc0ded);
-       CLASSERT(LNET_PROTO_TCP_VERSION_MAJOR == 1);
-       CLASSERT(LNET_PROTO_TCP_VERSION_MINOR == 0);
-       CLASSERT(LNET_MSG_ACK == 0);
-       CLASSERT(LNET_MSG_PUT == 1);
-       CLASSERT(LNET_MSG_GET == 2);
-       CLASSERT(LNET_MSG_REPLY == 3);
-       CLASSERT(LNET_MSG_HELLO == 4);
+       BUILD_BUG_ON(LNET_PROTO_TCP_MAGIC != 0xeebc0ded);
+       BUILD_BUG_ON(LNET_PROTO_TCP_VERSION_MAJOR != 1);
+       BUILD_BUG_ON(LNET_PROTO_TCP_VERSION_MINOR != 0);
+       BUILD_BUG_ON(LNET_MSG_ACK != 0);
+       BUILD_BUG_ON(LNET_MSG_PUT != 1);
+       BUILD_BUG_ON(LNET_MSG_GET != 2);
+       BUILD_BUG_ON(LNET_MSG_REPLY != 3);
+       BUILD_BUG_ON(LNET_MSG_HELLO != 4);
 
        /* Checks for struct lnet_handle_wire */
-       CLASSERT((int)sizeof(struct lnet_handle_wire) == 16);
-       CLASSERT((int)offsetof(struct lnet_handle_wire, wh_interface_cookie) == 0);
-       CLASSERT((int)sizeof(((struct lnet_handle_wire *)0)->wh_interface_cookie) == 8);
-       CLASSERT((int)offsetof(struct lnet_handle_wire, wh_object_cookie) == 8);
-       CLASSERT((int)sizeof(((struct lnet_handle_wire *)0)->wh_object_cookie) == 8);
+       BUILD_BUG_ON((int)sizeof(struct lnet_handle_wire) != 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_handle_wire,
+                                  wh_interface_cookie) != 0);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_handle_wire *)0)->wh_interface_cookie) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_handle_wire,
+                                  wh_object_cookie) != 8);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_handle_wire *)0)->wh_object_cookie) != 8);
 
        /* Checks for struct struct lnet_magicversion */
-       CLASSERT((int)sizeof(struct lnet_magicversion) == 8);
-       CLASSERT((int)offsetof(struct lnet_magicversion, magic) == 0);
-       CLASSERT((int)sizeof(((struct lnet_magicversion *)0)->magic) == 4);
-       CLASSERT((int)offsetof(struct lnet_magicversion, version_major) == 4);
-       CLASSERT((int)sizeof(((struct lnet_magicversion *)0)->version_major) == 2);
-       CLASSERT((int)offsetof(struct lnet_magicversion, version_minor) == 6);
-       CLASSERT((int)sizeof(((struct lnet_magicversion *)0)->version_minor) == 2);
+       BUILD_BUG_ON((int)sizeof(struct lnet_magicversion) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, magic) != 0);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->magic) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, version_major) != 4);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->version_major) != 2);
+       BUILD_BUG_ON((int)offsetof(struct lnet_magicversion,
+                                  version_minor) != 6);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->version_minor) != 2);
 
        /* Checks for struct struct lnet_hdr */
-       CLASSERT((int)sizeof(struct lnet_hdr) == 72);
-       CLASSERT((int)offsetof(struct lnet_hdr, dest_nid) == 0);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->dest_nid) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, src_nid) == 8);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->src_nid) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, dest_pid) == 16);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->dest_pid) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, src_pid) == 20);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->src_pid) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, type) == 24);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->type) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, payload_length) == 28);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->payload_length) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg) == 32);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg) == 40);
+       BUILD_BUG_ON((int)sizeof(struct lnet_hdr) != 72);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, dest_nid) != 0);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->dest_nid) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, src_nid) != 8);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->src_nid) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, dest_pid) != 16);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->dest_pid) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, src_pid) != 20);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->src_pid) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, type) != 24);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->type) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, payload_length) != 28);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->payload_length) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg) != 32);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg) != 40);
 
        /* Ack */
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.ack.dst_wmd) == 32);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.ack.dst_wmd) == 16);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.ack.match_bits) == 48);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.ack.match_bits) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.ack.mlength) == 56);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.ack.mlength) == 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.dst_wmd) != 32);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.dst_wmd) != 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.match_bits) != 48);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.match_bits) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.mlength) != 56);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.mlength) != 4);
 
        /* Put */
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.put.ack_wmd) == 32);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.ack_wmd) == 16);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.put.match_bits) == 48);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.match_bits) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.put.hdr_data) == 56);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.hdr_data) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.put.ptl_index) == 64);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.ptl_index) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.put.offset) == 68);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.put.offset) == 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.ack_wmd) != 32);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.ack_wmd) != 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.match_bits) != 48);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.match_bits) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.hdr_data) != 56);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.hdr_data) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.ptl_index) != 64);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.ptl_index) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.offset) != 68);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.offset) != 4);
 
        /* Get */
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.get.return_wmd) == 32);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.return_wmd) == 16);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.get.match_bits) == 48);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.match_bits) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.get.ptl_index) == 56);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.ptl_index) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.get.src_offset) == 60);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.src_offset) == 4);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.get.sink_length) == 64);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.get.sink_length) == 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.return_wmd) != 32);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.return_wmd) != 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.match_bits) != 48);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.match_bits) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.ptl_index) != 56);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.ptl_index) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.src_offset) != 60);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.src_offset) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.sink_length) != 64);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.sink_length) != 4);
 
        /* Reply */
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.reply.dst_wmd) == 32);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.reply.dst_wmd) == 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.reply.dst_wmd) != 32);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.reply.dst_wmd) != 16);
 
        /* Hello */
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.hello.incarnation) == 32);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.hello.incarnation) == 8);
-       CLASSERT((int)offsetof(struct lnet_hdr, msg.hello.type) == 40);
-       CLASSERT((int)sizeof(((struct lnet_hdr *)0)->msg.hello.type) == 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.hello.incarnation) != 32);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.hello.incarnation) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.hello.type) != 40);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.hello.type) != 4);
 
        /* Checks for struct lnet_ni_status and related constants */
-       CLASSERT(LNET_NI_STATUS_INVALID == 0x00000000);
-       CLASSERT(LNET_NI_STATUS_UP == 0x15aac0de);
-       CLASSERT(LNET_NI_STATUS_DOWN == 0xdeadface);
+       BUILD_BUG_ON(LNET_NI_STATUS_INVALID != 0x00000000);
+       BUILD_BUG_ON(LNET_NI_STATUS_UP != 0x15aac0de);
+       BUILD_BUG_ON(LNET_NI_STATUS_DOWN != 0xdeadface);
 
        /* Checks for struct lnet_ni_status */
-       CLASSERT((int)sizeof(struct lnet_ni_status) == 16);
-       CLASSERT((int)offsetof(struct lnet_ni_status, ns_nid) == 0);
-       CLASSERT((int)sizeof(((struct lnet_ni_status *)0)->ns_nid) == 8);
-       CLASSERT((int)offsetof(struct lnet_ni_status, ns_status) == 8);
-       CLASSERT((int)sizeof(((struct lnet_ni_status *)0)->ns_status) == 4);
-       CLASSERT((int)offsetof(struct lnet_ni_status, ns_unused) == 12);
-       CLASSERT((int)sizeof(((struct lnet_ni_status *)0)->ns_unused) == 4);
+       BUILD_BUG_ON((int)sizeof(struct lnet_ni_status) != 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ni_status, ns_nid) != 0);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ni_status *)0)->ns_nid) != 8);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ni_status, ns_status) != 8);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ni_status *)0)->ns_status) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ni_status, ns_unused) != 12);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ni_status *)0)->ns_unused) != 4);
 
        /* Checks for struct lnet_ping_info and related constants */
-       CLASSERT(LNET_PROTO_PING_MAGIC == 0x70696E67);
-       CLASSERT(LNET_PING_FEAT_INVAL == 0);
-       CLASSERT(LNET_PING_FEAT_BASE == 1);
-       CLASSERT(LNET_PING_FEAT_NI_STATUS == 2);
-       CLASSERT(LNET_PING_FEAT_RTE_DISABLED == 4);
-       CLASSERT(LNET_PING_FEAT_MULTI_RAIL == 8);
-       CLASSERT(LNET_PING_FEAT_DISCOVERY == 16);
-       CLASSERT(LNET_PING_FEAT_BITS == 31);
+       BUILD_BUG_ON(LNET_PROTO_PING_MAGIC != 0x70696E67);
+       BUILD_BUG_ON(LNET_PING_FEAT_INVAL != 0);
+       BUILD_BUG_ON(LNET_PING_FEAT_BASE != 1);
+       BUILD_BUG_ON(LNET_PING_FEAT_NI_STATUS != 2);
+       BUILD_BUG_ON(LNET_PING_FEAT_RTE_DISABLED != 4);
+       BUILD_BUG_ON(LNET_PING_FEAT_MULTI_RAIL != 8);
+       BUILD_BUG_ON(LNET_PING_FEAT_DISCOVERY != 16);
+       BUILD_BUG_ON(LNET_PING_FEAT_BITS != 31);
 
        /* Checks for struct lnet_ping_info */
-       CLASSERT((int)sizeof(struct lnet_ping_info) == 16);
-       CLASSERT((int)offsetof(struct lnet_ping_info, pi_magic) == 0);
-       CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_magic) == 4);
-       CLASSERT((int)offsetof(struct lnet_ping_info, pi_features) == 4);
-       CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_features) == 4);
-       CLASSERT((int)offsetof(struct lnet_ping_info, pi_pid) == 8);
-       CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_pid) == 4);
-       CLASSERT((int)offsetof(struct lnet_ping_info, pi_nnis) == 12);
-       CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_nnis) == 4);
-       CLASSERT((int)offsetof(struct lnet_ping_info, pi_ni) == 16);
-       CLASSERT((int)sizeof(((struct lnet_ping_info *)0)->pi_ni) == 0);
+       BUILD_BUG_ON((int)sizeof(struct lnet_ping_info) != 16);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_magic) != 0);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_magic) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_features) != 4);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_features) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_pid) != 8);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_pid) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_nnis) != 12);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_nnis) != 4);
+       BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_ni) != 16);
+       BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_ni) != 0);
 }
 
-static struct lnet_lnd *lnet_find_lnd_by_type(__u32 type)
+static const struct lnet_lnd *lnet_find_lnd_by_type(__u32 type)
 {
-       struct lnet_lnd *lnd;
-       struct list_head *tmp;
+       const struct lnet_lnd *lnd;
 
        /* holding lnd mutex */
-       list_for_each(tmp, &the_lnet.ln_lnds) {
-               lnd = list_entry(tmp, struct lnet_lnd, lnd_list);
+       if (type >= NUM_LNDS)
+               return NULL;
+       lnd = the_lnet.ln_lnds[type];
+       LASSERT(!lnd || lnd->lnd_type == type);
 
-               if (lnd->lnd_type == type)
-                       return lnd;
-       }
-       return NULL;
+       return lnd;
 }
 
 unsigned int
@@ -817,15 +836,14 @@ lnet_get_lnd_timeout(void)
 EXPORT_SYMBOL(lnet_get_lnd_timeout);
 
 void
-lnet_register_lnd(struct lnet_lnd *lnd)
+lnet_register_lnd(const struct lnet_lnd *lnd)
 {
        mutex_lock(&the_lnet.ln_lnd_mutex);
 
        LASSERT(libcfs_isknown_lnd(lnd->lnd_type));
        LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == NULL);
 
-       list_add_tail(&lnd->lnd_list, &the_lnet.ln_lnds);
-       lnd->lnd_refcount = 0;
+       the_lnet.ln_lnds[lnd->lnd_type] = lnd;
 
        CDEBUG(D_NET, "%s LND registered\n", libcfs_lnd2str(lnd->lnd_type));
 
@@ -834,14 +852,13 @@ lnet_register_lnd(struct lnet_lnd *lnd)
 EXPORT_SYMBOL(lnet_register_lnd);
 
 void
-lnet_unregister_lnd(struct lnet_lnd *lnd)
+lnet_unregister_lnd(const struct lnet_lnd *lnd)
 {
        mutex_lock(&the_lnet.ln_lnd_mutex);
 
        LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == lnd);
-       LASSERT(lnd->lnd_refcount == 0);
 
-       list_del(&lnd->lnd_list);
+       the_lnet.ln_lnds[lnd->lnd_type] = NULL;
        CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type));
 
        mutex_unlock(&the_lnet.ln_lnd_mutex);
@@ -1097,6 +1114,26 @@ lnet_res_lh_initialize(struct lnet_res_container *rec,
        list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]);
 }
 
+struct list_head **
+lnet_create_array_of_queues(void)
+{
+       struct list_head **qs;
+       struct list_head *q;
+       int i;
+
+       qs = cfs_percpt_alloc(lnet_cpt_table(),
+                             sizeof(struct list_head));
+       if (!qs) {
+               CERROR("Failed to allocate queues\n");
+               return NULL;
+       }
+
+       cfs_percpt_for_each(q, i, qs)
+               INIT_LIST_HEAD(q);
+
+       return qs;
+}
+
 static int lnet_unprepare(void);
 
 static int
@@ -1131,8 +1168,9 @@ lnet_prepare(lnet_pid_t requested_pid)
        INIT_LIST_HEAD(&the_lnet.ln_mt_peerNIRecovq);
        init_waitqueue_head(&the_lnet.ln_dc_waitq);
        LNetInvalidateEQHandle(&the_lnet.ln_mt_eqh);
+       init_completion(&the_lnet.ln_started);
 
-       rc = lnet_descriptor_setup();
+       rc = lnet_slab_setup();
        if (rc != 0)
                goto failed;
 
@@ -1167,14 +1205,6 @@ lnet_prepare(lnet_pid_t requested_pid)
        if (rc != 0)
                goto failed;
 
-       recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME);
-       if (recs == NULL) {
-               rc = -ENOMEM;
-               goto failed;
-       }
-
-       the_lnet.ln_me_containers = recs;
-
        recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD);
        if (recs == NULL) {
                rc = -ENOMEM;
@@ -1189,6 +1219,12 @@ lnet_prepare(lnet_pid_t requested_pid)
                goto failed;
        }
 
+       the_lnet.ln_mt_zombie_rstqs = lnet_create_array_of_queues();
+       if (!the_lnet.ln_mt_zombie_rstqs) {
+               rc = -ENOMEM;
+               goto failed;
+       }
+
        return 0;
 
  failed:
@@ -1212,6 +1248,11 @@ lnet_unprepare (void)
        LASSERT(list_empty(&the_lnet.ln_test_peers));
        LASSERT(list_empty(&the_lnet.ln_nets));
 
+       if (the_lnet.ln_mt_zombie_rstqs) {
+               lnet_clean_zombie_rstqs();
+               the_lnet.ln_mt_zombie_rstqs = NULL;
+       }
+
        if (!LNetEQHandleIsInvalid(the_lnet.ln_mt_eqh)) {
                rc = LNetEQFree(the_lnet.ln_mt_eqh);
                LNetInvalidateEQHandle(&the_lnet.ln_mt_eqh);
@@ -1225,11 +1266,6 @@ lnet_unprepare (void)
                the_lnet.ln_md_containers = NULL;
        }
 
-       if (the_lnet.ln_me_containers != NULL) {
-               lnet_res_containers_destroy(the_lnet.ln_me_containers);
-               the_lnet.ln_me_containers = NULL;
-       }
-
        lnet_res_container_cleanup(&the_lnet.ln_eq_container);
 
        lnet_msg_containers_destroy();
@@ -1241,7 +1277,7 @@ lnet_unprepare (void)
                the_lnet.ln_counters = NULL;
        }
        lnet_destroy_remote_nets_table();
-       lnet_descriptor_cleanup();
+       lnet_slab_cleanup();
 
        return 0;
 }
@@ -1366,18 +1402,28 @@ lnet_cpt_of_nid(lnet_nid_t nid, struct lnet_ni *ni)
 EXPORT_SYMBOL(lnet_cpt_of_nid);
 
 int
-lnet_islocalnet(__u32 net_id)
+lnet_islocalnet_locked(__u32 net_id)
 {
        struct lnet_net *net;
-       int             cpt;
-       bool            local;
-
-       cpt = lnet_net_lock_current();
+       bool local;
 
        net = lnet_get_net_locked(net_id);
 
        local = net != NULL;
 
+       return local;
+}
+
+int
+lnet_islocalnet(__u32 net_id)
+{
+       int cpt;
+       bool local;
+
+       cpt = lnet_net_lock_current();
+
+       local = lnet_islocalnet_locked(net_id);
+
        lnet_net_unlock(cpt);
 
        return local;
@@ -1467,7 +1513,7 @@ lnet_ping_buffer_alloc(int nnis, gfp_t gfp)
 void
 lnet_ping_buffer_free(struct lnet_ping_buffer *pbuf)
 {
-       LASSERT(lnet_ping_buffer_numref(pbuf) == 0);
+       LASSERT(atomic_read(&pbuf->pb_refcnt) == 0);
        LIBCFS_FREE(pbuf, LNET_PING_BUFFER_SIZE(pbuf->pb_nnis));
 }
 
@@ -1535,6 +1581,44 @@ lnet_get_ni_count(void)
 }
 
 int
+lnet_get_net_count(void)
+{
+       struct lnet_net *net;
+       int count = 0;
+
+       lnet_net_lock(0);
+
+       list_for_each_entry(net, &the_lnet.ln_nets, net_list) {
+               count++;
+       }
+
+       lnet_net_unlock(0);
+
+       return count;
+}
+
+void
+lnet_swap_pinginfo(struct lnet_ping_buffer *pbuf)
+{
+       struct lnet_ni_status *stat;
+       int nnis;
+       int i;
+
+       __swab32s(&pbuf->pb_info.pi_magic);
+       __swab32s(&pbuf->pb_info.pi_features);
+       __swab32s(&pbuf->pb_info.pi_pid);
+       __swab32s(&pbuf->pb_info.pi_nnis);
+       nnis = pbuf->pb_info.pi_nnis;
+       if (nnis > pbuf->pb_nnis)
+               nnis = pbuf->pb_nnis;
+       for (i = 0; i < nnis; i++) {
+               stat = &pbuf->pb_info.pi_ni[i];
+               __swab64s(&stat->ns_nid);
+               __swab32s(&stat->ns_status);
+       }
+}
+
+int
 lnet_ping_info_validate(struct lnet_ping_info *pinfo)
 {
        if (!pinfo)
@@ -1591,7 +1675,7 @@ lnet_ping_target_setup(struct lnet_ping_buffer **ppbuf,
                .nid = LNET_NID_ANY,
                .pid = LNET_PID_ANY
        };
-       struct lnet_handle_me me_handle;
+       struct lnet_me *me;
        struct lnet_md md = { NULL };
        int rc, rc2;
 
@@ -1611,11 +1695,11 @@ lnet_ping_target_setup(struct lnet_ping_buffer **ppbuf,
        }
 
        /* Ping target ME/MD */
-       rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
+       me = LNetMEAttach(LNET_RESERVED_PORTAL, id,
                          LNET_PROTO_PING_MATCHBITS, 0,
-                         LNET_UNLINK, LNET_INS_AFTER,
-                         &me_handle);
-       if (rc != 0) {
+                         LNET_UNLINK, LNET_INS_AFTER);
+       if (IS_ERR(me)) {
+               rc = PTR_ERR(me);
                CERROR("Can't create ping target ME: %d\n", rc);
                goto fail_decref_ping_buffer;
        }
@@ -1630,7 +1714,7 @@ lnet_ping_target_setup(struct lnet_ping_buffer **ppbuf,
        md.eq_handle = the_lnet.ln_ping_target_eq;
        md.user_ptr  = *ppbuf;
 
-       rc = LNetMDAttach(me_handle, md, LNET_RETAIN, ping_mdh);
+       rc = LNetMDAttach(me, md, LNET_RETAIN, ping_mdh);
        if (rc != 0) {
                CERROR("Can't attach ping target MD: %d\n", rc);
                goto fail_unlink_ping_me;
@@ -1640,10 +1724,9 @@ lnet_ping_target_setup(struct lnet_ping_buffer **ppbuf,
        return 0;
 
 fail_unlink_ping_me:
-       rc2 = LNetMEUnlink(me_handle);
-       LASSERT(rc2 == 0);
+       LNetMEUnlink(me);
 fail_decref_ping_buffer:
-       LASSERT(lnet_ping_buffer_numref(*ppbuf) == 1);
+       LASSERT(atomic_read(&(*ppbuf)->pb_refcnt) == 1);
        lnet_ping_buffer_decref(*ppbuf);
        *ppbuf = NULL;
 fail_free_eq:
@@ -1664,10 +1747,9 @@ lnet_ping_md_unlink(struct lnet_ping_buffer *pbuf,
        LNetInvalidateMDHandle(ping_mdh);
 
        /* NB the MD could be busy; this just starts the unlink */
-       while (lnet_ping_buffer_numref(pbuf) > 1) {
+       while (atomic_read(&pbuf->pb_refcnt) > 1) {
                CDEBUG(D_NET, "Still waiting for ping data MD to unlink\n");
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(cfs_time_seconds(1));
+               schedule_timeout_uninterruptible(cfs_time_seconds(1));
        }
 
        cfs_restore_sigs(blocked);
@@ -1773,7 +1855,7 @@ int lnet_push_target_resize(void)
 {
        struct lnet_process_id id = { LNET_NID_ANY, LNET_PID_ANY };
        struct lnet_md md = { NULL };
-       struct lnet_handle_me meh;
+       struct lnet_me *me;
        struct lnet_handle_md mdh;
        struct lnet_handle_md old_mdh;
        struct lnet_ping_buffer *pbuf;
@@ -1792,11 +1874,12 @@ again:
                goto fail_return;
        }
 
-       rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
+       me = LNetMEAttach(LNET_RESERVED_PORTAL, id,
                          LNET_PROTO_PING_MATCHBITS, 0,
-                         LNET_UNLINK, LNET_INS_AFTER,
-                         &meh);
-       if (rc) {
+                         LNET_UNLINK, LNET_INS_AFTER);
+
+       if (IS_ERR(me)) {
+               rc = PTR_ERR(me);
                CERROR("Can't create push target ME: %d\n", rc);
                goto fail_decref_pbuf;
        }
@@ -1811,10 +1894,10 @@ again:
        md.user_ptr  = pbuf;
        md.eq_handle = the_lnet.ln_push_target_eq;
 
-       rc = LNetMDAttach(meh, md, LNET_RETAIN, &mdh);
+       rc = LNetMDAttach(me, md, LNET_RETAIN, &mdh);
        if (rc) {
                CERROR("Can't attach push MD: %d\n", rc);
-               goto fail_unlink_meh;
+               goto fail_unlink_me;
        }
        lnet_ping_buffer_addref(pbuf);
 
@@ -1837,8 +1920,8 @@ again:
 
        return 0;
 
-fail_unlink_meh:
-       LNetMEUnlink(meh);
+fail_unlink_me:
+       LNetMEUnlink(me);
 fail_decref_pbuf:
        lnet_ping_buffer_decref(pbuf);
 fail_return:
@@ -1897,10 +1980,9 @@ static void lnet_push_target_fini(void)
        LNetInvalidateMDHandle(&the_lnet.ln_push_target_md);
 
        /* Wait for the unlink to complete. */
-       while (lnet_ping_buffer_numref(the_lnet.ln_push_target) > 1) {
+       while (atomic_read(&the_lnet.ln_push_target->pb_refcnt) > 1) {
                CDEBUG(D_NET, "Still waiting for ping data MD to unlink\n");
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(cfs_time_seconds(1));
+               schedule_timeout_uninterruptible(cfs_time_seconds(1));
        }
 
        lnet_ping_buffer_decref(the_lnet.ln_push_target);
@@ -1976,8 +2058,7 @@ lnet_clear_zombies_nis_locked(struct lnet_net *net)
                                       "Waiting for zombie LNI %s\n",
                                       libcfs_nid2str(ni->ni_nid));
                        }
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(cfs_time_seconds(1));
+                       schedule_timeout_uninterruptible(cfs_time_seconds(1));
                        lnet_net_lock(LNET_LOCK_EX);
                        continue;
                }
@@ -1987,7 +2068,14 @@ lnet_clear_zombies_nis_locked(struct lnet_net *net)
                islo = ni->ni_net->net_lnd->lnd_type == LOLND;
 
                LASSERT(!in_interrupt());
+               /* Holding the mutex makes it safe for lnd_shutdown
+                * to call module_put(). Module unload cannot finish
+                * until lnet_unregister_lnd() completes, and that
+                * requires the mutex.
+                */
+               mutex_lock(&the_lnet.ln_lnd_mutex);
                (net->net_lnd->lnd_shutdown)(ni);
+               mutex_unlock(&the_lnet.ln_lnd_mutex);
 
                if (!islo)
                        CDEBUG(D_LNI, "Removed LNI %s\n",
@@ -2030,8 +2118,6 @@ lnet_shutdown_lndnet(struct lnet_net *net)
 
        lnet_net_lock(LNET_LOCK_EX);
 
-       net->net_state = LNET_NET_STATE_DELETING;
-
        list_del_init(&net->net_list);
 
        while (!list_empty(&net->net_ni_list)) {
@@ -2047,15 +2133,6 @@ lnet_shutdown_lndnet(struct lnet_net *net)
        /* Do peer table cleanup for this net */
        lnet_peer_tables_cleanup(net);
 
-       lnet_net_lock(LNET_LOCK_EX);
-       /*
-        * decrement ref count on lnd only when the entire network goes
-        * away
-        */
-       net->net_lnd->lnd_refcount--;
-
-       lnet_net_unlock(LNET_LOCK_EX);
-
        lnet_net_free(net);
 }
 
@@ -2063,11 +2140,9 @@ static void
 lnet_shutdown_lndnets(void)
 {
        struct lnet_net *net;
-       struct list_head resend;
+       LIST_HEAD(resend);
        struct lnet_msg *msg, *tmp;
 
-       INIT_LIST_HEAD(&resend);
-
        /* NB called holding the global mutex */
 
        /* All quiet on the API front */
@@ -2139,9 +2214,6 @@ lnet_startup_lndni(struct lnet_ni *ni, struct lnet_lnd_tunables *tun)
        if (rc != 0) {
                LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n",
                                   rc, libcfs_lnd2str(net->net_lnd->lnd_type));
-               lnet_net_lock(LNET_LOCK_EX);
-               net->net_lnd->lnd_refcount--;
-               lnet_net_unlock(LNET_LOCK_EX);
                goto failed0;
        }
 
@@ -2201,21 +2273,19 @@ static int
 lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
 {
        struct lnet_ni *ni;
-       struct lnet_net *net_l = NULL;
-       struct list_head        local_ni_list;
-       int                     rc;
-       int                     ni_count = 0;
-       __u32                   lnd_type;
-       struct lnet_lnd *lnd;
-       int                     peer_timeout =
+       struct lnet_net *net_l = NULL;
+       LIST_HEAD(local_ni_list);
+       int rc;
+       int ni_count = 0;
+       __u32 lnd_type;
+       const struct lnet_lnd  *lnd;
+       int peer_timeout =
                net->net_tunables.lct_peer_timeout;
-       int                     maxtxcredits =
+       int maxtxcredits =
                net->net_tunables.lct_max_tx_credits;
-       int                     peerrtrcredits =
+       int peerrtrcredits =
                net->net_tunables.lct_peer_rtr_credits;
 
-       INIT_LIST_HEAD(&local_ni_list);
-
        /*
         * make sure that this net is unique. If it isn't then
         * we are adding interfaces to an already existing network, and
@@ -2250,10 +2320,6 @@ lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
                        }
                }
 
-               lnet_net_lock(LNET_LOCK_EX);
-               lnd->lnd_refcount++;
-               lnet_net_unlock(LNET_LOCK_EX);
-
                net->net_lnd = lnd;
 
                mutex_unlock(&the_lnet.ln_lnd_mutex);
@@ -2304,7 +2370,7 @@ lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
                 * up is actually unique. if it's not fail. */
                if (!lnet_ni_unique_net(&net_l->net_ni_list,
                                        ni->ni_interfaces[0])) {
-                       rc = -EINVAL;
+                       rc = -EEXIST;
                        goto failed1;
                }
 
@@ -2314,9 +2380,6 @@ lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
 
                rc = lnet_startup_lndni(ni, tun);
 
-               LASSERT(ni->ni_net->net_tunables.lct_peer_timeout <= 0 ||
-                       ni->ni_net->net_lnd->lnd_query != NULL);
-
                if (rc < 0)
                        goto failed1;
 
@@ -2341,7 +2404,6 @@ lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
                 */
                lnet_net_free(net);
        } else {
-               net->net_state = LNET_NET_STATE_ACTIVE;
                /*
                 * restore tunables after it has been overwitten by the
                 * lnd
@@ -2358,6 +2420,9 @@ lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
                lnet_net_unlock(LNET_LOCK_EX);
        }
 
+       /* update net count */
+       lnet_current_net_count = lnet_get_net_count();
+
        return ni_count;
 
 failed1:
@@ -2452,12 +2517,8 @@ int lnet_lib_init(void)
        }
 
        the_lnet.ln_refcount = 0;
-       LNetInvalidateEQHandle(&the_lnet.ln_rc_eqh);
-       INIT_LIST_HEAD(&the_lnet.ln_lnds);
        INIT_LIST_HEAD(&the_lnet.ln_net_zombie);
-       INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie);
        INIT_LIST_HEAD(&the_lnet.ln_msg_resend);
-       INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow);
 
        /* The hash table size is the number of bits it takes to express the set
         * ln_num_routes, minus 1 (better to under estimate than over so we
@@ -2481,14 +2542,18 @@ int lnet_lib_init(void)
  *
  * \pre lnet_lib_init() called with success.
  * \pre All LNet users called LNetNIFini() for matching LNetNIInit() calls.
+ *
+ * As this happens at module-unload, all lnds must already be unloaded,
+ * so they must already be unregistered.
  */
 void lnet_lib_exit(void)
 {
-       LASSERT(the_lnet.ln_refcount == 0);
+       int i;
 
-       while (!list_empty(&the_lnet.ln_lnds))
-               lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next,
-                                              struct lnet_lnd, lnd_list));
+       LASSERT(the_lnet.ln_refcount == 0);
+       lnet_unregister_lnd(&the_lolnd);
+       for (i = 0; i < NUM_LNDS; i++)
+               LASSERT(!the_lnet.ln_lnds[i]);
        lnet_destroy_locks();
 }
 
@@ -2515,11 +2580,9 @@ LNetNIInit(lnet_pid_t requested_pid)
        int                     ni_count;
        struct lnet_ping_buffer *pbuf;
        struct lnet_handle_md   ping_mdh;
-       struct list_head        net_head;
+       LIST_HEAD(net_head);
        struct lnet_net         *net;
 
-       INIT_LIST_HEAD(&net_head);
-
        mutex_lock(&the_lnet.ln_api_mutex);
 
        CDEBUG(D_OTHER, "refs %d\n", the_lnet.ln_refcount);
@@ -2573,10 +2636,6 @@ LNetNIInit(lnet_pid_t requested_pid)
                if (rc != 0)
                        goto err_shutdown_lndnis;
 
-               rc = lnet_check_routes();
-               if (rc != 0)
-                       goto err_destroy_routes;
-
                rc = lnet_rtrpools_alloc(im_a_router);
                if (rc != 0)
                        goto err_destroy_routes;
@@ -2601,29 +2660,34 @@ LNetNIInit(lnet_pid_t requested_pid)
                goto err_stop_ping;
        }
 
-       rc = lnet_monitor_thr_start();
-       if (rc != 0)
-               goto err_stop_ping;
-
        rc = lnet_push_target_init();
        if (rc != 0)
-               goto err_stop_monitor_thr;
+               goto err_stop_ping;
 
        rc = lnet_peer_discovery_start();
        if (rc != 0)
                goto err_destroy_push_target;
 
+       rc = lnet_monitor_thr_start();
+       if (rc != 0)
+               goto err_stop_discovery_thr;
+
        lnet_fault_init();
        lnet_router_debugfs_init();
 
        mutex_unlock(&the_lnet.ln_api_mutex);
 
+       complete_all(&the_lnet.ln_started);
+
+       /* wait for all routers to start */
+       lnet_wait_router_start();
+
        return 0;
 
+err_stop_discovery_thr:
+       lnet_peer_discovery_stop();
 err_destroy_push_target:
        lnet_push_target_fini();
-err_stop_monitor_thr:
-       lnet_monitor_thr_stop();
 err_stop_ping:
        lnet_ping_target_fini();
 err_acceptor_stop:
@@ -2659,7 +2723,7 @@ EXPORT_SYMBOL(LNetNIInit);
  * \return always 0 for current implementation.
  */
 int
-LNetNIFini()
+LNetNIFini(void)
 {
        mutex_lock(&the_lnet.ln_api_mutex);
 
@@ -2673,9 +2737,9 @@ LNetNIFini()
                lnet_fault_fini();
 
                lnet_router_debugfs_fini();
+               lnet_monitor_thr_stop();
                lnet_peer_discovery_stop();
                lnet_push_target_fini();
-               lnet_monitor_thr_stop();
                lnet_ping_target_fini();
 
                /* Teardown fns that use my own API functions BEFORE here */
@@ -3105,9 +3169,7 @@ static int lnet_handle_legacy_ip2nets(char *ip2nets,
        struct lnet_net *net;
        char *nets;
        int rc;
-       struct list_head net_head;
-
-       INIT_LIST_HEAD(&net_head);
+       LIST_HEAD(net_head);
 
        rc = lnet_parse_ip2nets(&nets, ip2nets);
        if (rc < 0)
@@ -3286,14 +3348,12 @@ unlock_api_mutex:
 int
 lnet_dyn_add_net(struct lnet_ioctl_config_data *conf)
 {
-       struct lnet_net         *net;
-       struct list_head        net_head;
-       int                     rc;
+       struct lnet_net *net;
+       LIST_HEAD(net_head);
+       int rc;
        struct lnet_ioctl_config_lnd_tunables tun;
        char *nets = conf->cfg_config_u.cfg_net.net_intf;
 
-       INIT_LIST_HEAD(&net_head);
-
        /* Create a net/ni structures for the network string */
        rc = lnet_parse_networks(&net_head, nets, use_tcp_bonding);
        if (rc <= 0)
@@ -3513,26 +3573,28 @@ LNetCtl(unsigned int cmd, void *arg)
        case IOC_LIBCFS_FAIL_NID:
                return lnet_fail_nid(data->ioc_nid, data->ioc_count);
 
-       case IOC_LIBCFS_ADD_ROUTE:
+       case IOC_LIBCFS_ADD_ROUTE: {
+               /* default router sensitivity to 1 */
+               unsigned int sensitivity = 1;
                config = arg;
 
                if (config->cfg_hdr.ioc_len < sizeof(*config))
                        return -EINVAL;
 
+               if (config->cfg_config_u.cfg_route.rtr_sensitivity) {
+                       sensitivity =
+                         config->cfg_config_u.cfg_route.rtr_sensitivity;
+               }
+
                mutex_lock(&the_lnet.ln_api_mutex);
                rc = lnet_add_route(config->cfg_net,
                                    config->cfg_config_u.cfg_route.rtr_hop,
                                    config->cfg_nid,
                                    config->cfg_config_u.cfg_route.
-                                       rtr_priority);
-               if (rc == 0) {
-                       rc = lnet_check_routes();
-                       if (rc != 0)
-                               lnet_del_route(config->cfg_net,
-                                              config->cfg_nid);
-               }
+                                       rtr_priority, sensitivity);
                mutex_unlock(&the_lnet.ln_api_mutex);
                return rc;
+       }
 
        case IOC_LIBCFS_DEL_ROUTE:
                config = arg;
@@ -3558,7 +3620,9 @@ LNetCtl(unsigned int cmd, void *arg)
                                    &config->cfg_nid,
                                    &config->cfg_config_u.cfg_route.rtr_flags,
                                    &config->cfg_config_u.cfg_route.
-                                       rtr_priority);
+                                       rtr_priority,
+                                   &config->cfg_config_u.cfg_route.
+                                       rtr_sensitivity);
                mutex_unlock(&the_lnet.ln_api_mutex);
                return rc;
 
@@ -3832,7 +3896,7 @@ LNetCtl(unsigned int cmd, void *arg)
                 * that deadline to the wall clock.
                 */
                deadline += ktime_get_seconds();
-               return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
+               return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, false,
                                   deadline);
        }
 
@@ -3845,9 +3909,7 @@ LNetCtl(unsigned int cmd, void *arg)
                return 0;
 
        case IOC_LIBCFS_TESTPROTOCOMPAT:
-               lnet_net_lock(LNET_LOCK_EX);
                the_lnet.ln_testprotocompat = data->ioc_flags;
-               lnet_net_unlock(LNET_LOCK_EX);
                return 0;
 
        case IOC_LIBCFS_LNET_FAULT:
@@ -3862,9 +3924,9 @@ LNetCtl(unsigned int cmd, void *arg)
                /* If timeout is negative then set default of 3 minutes */
                if (((s32)data->ioc_u32[1] <= 0) ||
                    data->ioc_u32[1] > (DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC))
-                       timeout = msecs_to_jiffies(DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC);
+                       timeout = cfs_time_seconds(DEFAULT_PEER_TIMEOUT);
                else
-                       timeout = msecs_to_jiffies(data->ioc_u32[1]);
+                       timeout = nsecs_to_jiffies(data->ioc_u32[1] * NSEC_PER_MSEC);
 
                rc = lnet_ping(id, timeout, data->ioc_pbuf1,
                               data->ioc_plen1 / sizeof(struct lnet_process_id));
@@ -3884,9 +3946,9 @@ LNetCtl(unsigned int cmd, void *arg)
                /* If timeout is negative then set default of 3 minutes */
                if (((s32)ping->op_param) <= 0 ||
                    ping->op_param > (DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC))
-                       timeout = msecs_to_jiffies(DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC);
+                       timeout = cfs_time_seconds(DEFAULT_PEER_TIMEOUT);
                else
-                       timeout = msecs_to_jiffies(ping->op_param);
+                       timeout = nsecs_to_jiffies(ping->op_param * NSEC_PER_MSEC);
 
                rc = lnet_ping(ping->ping_id, timeout,
                               ping->ping_buf,
@@ -4032,7 +4094,7 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout,
        int which;
        int unlinked = 0;
        int replied = 0;
-       const signed long a_long_time = msecs_to_jiffies(60 * MSEC_PER_SEC);
+       const signed long a_long_time = cfs_time_seconds(60);
        struct lnet_ping_buffer *pbuf;
        struct lnet_process_id tmpid;
        int i;