+ /* make sure that the the NI we're about to start
+ * 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;
+ goto failed1;
+ }
+
+ /* adjust the pointer the parent network, just in case it
+ * the net is a duplicate */
+ ni->ni_net = net_l;
+
+ 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;
+
+ lnet_ni_addref(ni);
+ list_add_tail(&ni->ni_netlist, &local_ni_list);
+
+ ni_count++;
+ }
+
+ lnet_net_lock(LNET_LOCK_EX);
+ list_splice_tail(&local_ni_list, &net_l->net_ni_list);
+ lnet_incr_dlc_seq();
+ lnet_net_unlock(LNET_LOCK_EX);
+
+ /* if the network is not unique then we don't want to keep
+ * it around after we're done. Free it. Otherwise add that
+ * net to the global the_lnet.ln_nets */
+ if (net_l != net && net_l != NULL) {
+ /*
+ * TODO - note. currently the tunables can not be updated
+ * once added
+ */
+ lnet_net_free(net);
+ } else {
+ net->net_state = LNET_NET_STATE_ACTIVE;
+ /*
+ * restore tunables after it has been overwitten by the
+ * lnd
+ */
+ if (peer_timeout != -1)
+ net->net_tunables.lct_peer_timeout = peer_timeout;
+ if (maxtxcredits != -1)
+ net->net_tunables.lct_max_tx_credits = maxtxcredits;
+ if (peerrtrcredits != -1)
+ net->net_tunables.lct_peer_rtr_credits = peerrtrcredits;
+
+ lnet_net_lock(LNET_LOCK_EX);
+ list_add_tail(&net->net_list, &the_lnet.ln_nets);
+ lnet_net_unlock(LNET_LOCK_EX);
+ }
+
+ return ni_count;
+
+failed1:
+ /*
+ * shutdown the new NIs that are being started up
+ * free the NET being started
+ */
+ while (!list_empty(&local_ni_list)) {
+ ni = list_entry(local_ni_list.next, struct lnet_ni,
+ ni_netlist);
+
+ lnet_shutdown_lndni(ni);
+ }
+
+failed0:
+ lnet_net_free(net);
+
+ return rc;
+}
+
+static int
+lnet_startup_lndnets(struct list_head *netlist)
+{
+ struct lnet_net *net;
+ int rc;
+ int ni_count = 0;
+
+ /*
+ * Change to running state before bringing up the LNDs. This
+ * allows lnet_shutdown_lndnets() to assert that we've passed
+ * through here.
+ */
+ lnet_net_lock(LNET_LOCK_EX);
+ the_lnet.ln_state = LNET_STATE_RUNNING;
+ lnet_net_unlock(LNET_LOCK_EX);
+
+ while (!list_empty(netlist)) {
+ net = list_entry(netlist->next, struct lnet_net, net_list);
+ list_del_init(&net->net_list);
+
+ rc = lnet_startup_lndnet(net, NULL);
+
+ if (rc < 0)
+ goto failed;
+
+ ni_count += rc;
+ }
+
+ return ni_count;
+failed:
+ lnet_shutdown_lndnets();
+
+ return rc;
+}
+
+/**
+ * Initialize LNet library.
+ *
+ * Automatically called at module loading time. Caller has to call
+ * lnet_lib_exit() after a call to lnet_lib_init(), if and only if the
+ * latter returned 0. It must be called exactly once.
+ *
+ * \retval 0 on success
+ * \retval -ve on failures.
+ */
+int lnet_lib_init(void)
+{
+ int rc;
+
+ lnet_assert_wire_constants();
+
+ memset(&the_lnet, 0, sizeof(the_lnet));
+
+ /* refer to global cfs_cpt_table for now */
+ the_lnet.ln_cpt_table = cfs_cpt_table;
+ the_lnet.ln_cpt_number = cfs_cpt_number(cfs_cpt_table);
+
+ LASSERT(the_lnet.ln_cpt_number > 0);
+ if (the_lnet.ln_cpt_number > LNET_CPT_MAX) {
+ /* we are under risk of consuming all lh_cookie */
+ CERROR("Can't have %d CPTs for LNet (max allowed is %d), "
+ "please change setting of CPT-table and retry\n",
+ the_lnet.ln_cpt_number, LNET_CPT_MAX);
+ return -E2BIG;
+ }
+
+ while ((1 << the_lnet.ln_cpt_bits) < the_lnet.ln_cpt_number)
+ the_lnet.ln_cpt_bits++;
+
+ rc = lnet_create_locks();
+ if (rc != 0) {
+ CERROR("Can't create LNet global locks: %d\n", rc);
+ return rc;
+ }
+
+ 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_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
+ * don't waste memory). */
+ if (rnet_htable_size <= 0)
+ rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
+ else if (rnet_htable_size > LNET_REMOTE_NETS_HASH_MAX)
+ rnet_htable_size = LNET_REMOTE_NETS_HASH_MAX;
+ the_lnet.ln_remote_nets_hbits = max_t(int, 1,