+kgnilnd_report_node_state(lnet_nid_t nid, int down)
+{
+ int rc;
+ kgn_peer_t *peer, *new_peer;
+ CFS_LIST_HEAD(zombies);
+
+ write_lock(&kgnilnd_data.kgn_peer_conn_lock);
+ peer = kgnilnd_find_peer_locked(nid);
+
+ if (peer == NULL) {
+ int i;
+ int found_net = 0;
+ kgn_net_t *net;
+
+ write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
+
+ /* Don't add a peer for node up events */
+ if (down == GNILND_RCA_NODE_UP) {
+ return 0;
+ }
+
+ /* find any valid net - we don't care which one... */
+ down_read(&kgnilnd_data.kgn_net_rw_sem);
+ for (i = 0; i < *kgnilnd_tunables.kgn_net_hash_size; i++) {
+ list_for_each_entry(net, &kgnilnd_data.kgn_nets[i],
+ gnn_list) {
+ found_net = 1;
+ break;
+ }
+
+ if (found_net) {
+ break;
+ }
+ }
+ up_read(&kgnilnd_data.kgn_net_rw_sem);
+
+ if (!found_net) {
+ CNETERR("Could not find a net for nid %lld\n", nid);
+ return 1;
+ }
+
+ /* The nid passed in does not yet contain the net portion.
+ * Let's build it up now
+ */
+ nid = LNET_MKNID(LNET_NIDNET(net->gnn_ni->ni_nid), nid);
+ rc = kgnilnd_add_peer(net, nid, &new_peer);
+
+ if (rc) {
+ CNETERR("Could not add peer for nid %lld, rc %d\n",
+ nid, rc);
+ return 1;
+ }
+
+ write_lock(&kgnilnd_data.kgn_peer_conn_lock);
+ peer = kgnilnd_find_peer_locked(nid);
+
+ if (peer == NULL) {
+ CNETERR("Could not find peer for nid %lld\n", nid);
+ write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
+ return 1;
+ }
+ }
+
+ peer->gnp_down = down;
+
+ if (down == GNILND_RCA_NODE_DOWN) {
+ kgn_conn_t *conn;
+
+ peer->gnp_down_event_time = jiffies;
+ kgnilnd_cancel_peer_connect_locked(peer, &zombies);
+ conn = kgnilnd_find_conn_locked(peer);
+
+ if (conn != NULL) {
+ kgnilnd_close_conn_locked(conn, -ENETRESET);
+ }
+ } else {
+ peer->gnp_up_event_time = jiffies;
+ }
+
+ write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
+
+ if (down == GNILND_RCA_NODE_DOWN) {
+ /* using ENETRESET so we don't get messages from
+ * kgnilnd_tx_done
+ */
+ kgnilnd_txlist_done(&zombies, -ENETRESET);
+
+ if (*kgnilnd_tunables.kgn_peer_health) {
+ kgnilnd_peer_notify(peer, -ECONNRESET);
+ }
+ }
+
+ CDEBUG(D_INFO, "marking nid %lld %s\n", nid, down ? "down" : "up");
+ return 0;
+}
+
+int