Whamcloud - gitweb
LU-2675 lmv: remove lmv_init_{lock,unlock}()
[fs/lustre-release.git] / lnet / ulnds / socklnd / conn.c
index 4d6e01d..424bf31 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  * GPL HEADER END
  */
 /*
- * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2012, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -128,6 +128,8 @@ usocklnd_tear_peer_conn(usock_conn_t *conn)
         lnet_process_id_t id;
         int               decref_flag  = 0;
         int               killall_flag = 0;
+        void             *rx_lnetmsg   = NULL; 
+       struct list_head   zombie_txs = LIST_HEAD_INIT(zombie_txs);
 
         if (peer == NULL) /* nothing to tear */
                 return;
@@ -142,11 +144,12 @@ usocklnd_tear_peer_conn(usock_conn_t *conn)
                 if (conn->uc_rx_state == UC_RX_LNET_PAYLOAD) {
                         /* change state not to finalize twice */
                         conn->uc_rx_state = UC_RX_KSM_HEADER;
-                        lnet_finalize(peer->up_ni, conn->uc_rx_lnetmsg, -EIO);
+                        /* stash lnetmsg while holding locks */
+                        rx_lnetmsg = conn->uc_rx_lnetmsg;
                 }
 
-                usocklnd_destroy_txlist(peer->up_ni,
-                                        &conn->uc_tx_list);
+                /* we cannot finilize txs right now (bug #18844) */
+               list_splice_init(&conn->uc_tx_list, &zombie_txs);
 
                 peer->up_conns[idx] = NULL;
                 conn->uc_peer = NULL;
@@ -154,6 +157,9 @@ usocklnd_tear_peer_conn(usock_conn_t *conn)
 
                 if(conn->uc_errored && !peer->up_errored)
                         peer->up_errored = killall_flag = 1;
+
+                /* prevent queueing new txs to this conn */
+                conn->uc_errored = 1;
         }
 
         pthread_mutex_unlock(&conn->uc_lock);
@@ -166,6 +172,11 @@ usocklnd_tear_peer_conn(usock_conn_t *conn)
         if (!decref_flag)
                 return;
 
+        if (rx_lnetmsg != NULL)
+                lnet_finalize(ni, rx_lnetmsg, -EIO);
+        
+        usocklnd_destroy_txlist(ni, &zombie_txs);
+
         usocklnd_conn_decref(conn);
         usocklnd_peer_decref(peer);
 
@@ -187,12 +198,12 @@ usocklnd_check_peer_stale(lnet_ni_t *ni, lnet_process_id_t id)
                 return;
         }
 
-        if (cfs_atomic_read(&peer->up_refcount) == 2) {
+       if (mt_atomic_read(&peer->up_refcount) == 2) {
                 int i;
                 for (i = 0; i < N_CONN_TYPES; i++)
                         LASSERT (peer->up_conns[i] == NULL);
 
-                list_del(&peer->up_list);
+               list_del(&peer->up_list);
 
                 if (peer->up_errored &&
                     (peer->up_peerid.pid & LNET_PID_USERFLAG) == 0)
@@ -238,10 +249,10 @@ usocklnd_create_passive_conn(lnet_ni_t *ni,
         conn->uc_state = UC_RECEIVING_HELLO;
         conn->uc_pt_idx = usocklnd_ip2pt_idx(peer_ip);
         conn->uc_ni = ni;
-        CFS_INIT_LIST_HEAD (&conn->uc_tx_list);
-        CFS_INIT_LIST_HEAD (&conn->uc_zcack_list);
+       INIT_LIST_HEAD(&conn->uc_tx_list);
+       INIT_LIST_HEAD(&conn->uc_zcack_list);
         pthread_mutex_init(&conn->uc_lock, NULL);
-        cfs_atomic_set(&conn->uc_refcount, 1); /* 1 ref for me */
+       mt_atomic_set(&conn->uc_refcount, 1); /* 1 ref for me */
 
         *connp = conn;
         return 0;
@@ -295,10 +306,10 @@ usocklnd_create_active_conn(usock_peer_t *peer, int type,
         conn->uc_peer       = peer;
 
         usocklnd_peer_addref(peer);
-        CFS_INIT_LIST_HEAD (&conn->uc_tx_list);
-        CFS_INIT_LIST_HEAD (&conn->uc_zcack_list);
+       INIT_LIST_HEAD(&conn->uc_tx_list);
+       INIT_LIST_HEAD(&conn->uc_zcack_list);
         pthread_mutex_init(&conn->uc_lock, NULL);
-        cfs_atomic_set(&conn->uc_refcount, 1); /* 1 ref for me */
+       mt_atomic_set(&conn->uc_refcount, 1); /* 1 ref for me */
 
         *connp = conn;
         return 0;
@@ -557,9 +568,9 @@ usocklnd_destroy_txlist(lnet_ni_t *ni, struct list_head *txlist)
 {
         usock_tx_t *tx;
 
-        while (!list_empty(txlist)) {
-                tx = list_entry(txlist->next, usock_tx_t, tx_list);
-                list_del(&tx->tx_list);
+       while (!list_empty(txlist)) {
+               tx = list_entry(txlist->next, usock_tx_t, tx_list);
+               list_del(&tx->tx_list);
 
                 usocklnd_destroy_tx(ni, tx);
         }
@@ -570,9 +581,10 @@ usocklnd_destroy_zcack_list(struct list_head *zcack_list)
 {
         usock_zc_ack_t *zcack;
 
-        while (!list_empty(zcack_list)) {
-                zcack = list_entry(zcack_list->next, usock_zc_ack_t, zc_list);
-                list_del(&zcack->zc_list);
+       while (!list_empty(zcack_list)) {
+               zcack = list_entry(zcack_list->next, usock_zc_ack_t,
+                                       zc_list);
+               list_del(&zcack->zc_list);
 
                 LIBCFS_FREE (zcack, sizeof(*zcack));
         }
@@ -605,7 +617,7 @@ usocklnd_destroy_conn(usock_conn_t *conn)
                 lnet_finalize(conn->uc_peer->up_ni, conn->uc_rx_lnetmsg, -EIO);
         }
 
-        if (!list_empty(&conn->uc_tx_list)) {
+       if (!list_empty(&conn->uc_tx_list)) {
                 LASSERT (conn->uc_peer != NULL);
                 usocklnd_destroy_txlist(conn->uc_peer->up_ni, &conn->uc_tx_list);
         }
@@ -658,13 +670,13 @@ int usocklnd_type2idx(int type)
 usock_peer_t *
 usocklnd_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id)
 {
-        struct list_head *peer_list = usocklnd_nid2peerlist(id.nid);
-        struct list_head *tmp;
+       struct list_head       *peer_list = usocklnd_nid2peerlist(id.nid);
+       struct list_head       *tmp;
         usock_peer_t     *peer;
 
-        list_for_each (tmp, peer_list) {
+       list_for_each(tmp, peer_list) {
 
-                peer = list_entry (tmp, usock_peer_t, up_list);
+               peer = list_entry(tmp, usock_peer_t, up_list);
 
                 if (peer->up_ni != ni)
                         continue;
@@ -699,7 +711,7 @@ usocklnd_create_peer(lnet_ni_t *ni, lnet_process_id_t id,
         peer->up_incrn_is_set = 0;
         peer->up_errored      = 0;
         peer->up_last_alive   = 0;
-        cfs_atomic_set (&peer->up_refcount, 1); /* 1 ref for caller */
+       mt_atomic_set(&peer->up_refcount, 1); /* 1 ref for caller */
         pthread_mutex_init(&peer->up_lock, NULL);
 
         pthread_mutex_lock(&net->un_lock);
@@ -744,8 +756,8 @@ usocklnd_find_or_create_peer(lnet_ni_t *ni, lnet_process_id_t id,
 
                 /* peer table will take 1 of my refs on peer */
                 usocklnd_peer_addref(peer);
-                list_add_tail (&peer->up_list,
-                               usocklnd_nid2peerlist(id.nid));
+               list_add_tail(&peer->up_list,
+                                   usocklnd_nid2peerlist(id.nid));
         } else {
                 usocklnd_peer_decref(peer); /* should destroy peer */
                 peer = peer2;
@@ -762,8 +774,8 @@ static int
 usocklnd_enqueue_zcack(usock_conn_t *conn, usock_zc_ack_t *zc_ack)
 {
         if (conn->uc_state == UC_READY &&
-            list_empty(&conn->uc_tx_list) &&
-            list_empty(&conn->uc_zcack_list) &&
+           list_empty(&conn->uc_tx_list) &&
+           list_empty(&conn->uc_zcack_list) &&
             !conn->uc_sending) {
                 int rc = usocklnd_add_pollrequest(conn, POLL_TX_SET_REQUEST,
                                                   POLLOUT);
@@ -771,7 +783,7 @@ usocklnd_enqueue_zcack(usock_conn_t *conn, usock_zc_ack_t *zc_ack)
                         return rc;
         }
 
-        list_add_tail(&zc_ack->zc_list, &conn->uc_zcack_list);
+       list_add_tail(&zc_ack->zc_list, &conn->uc_zcack_list);
         return 0;
 }
 
@@ -783,8 +795,8 @@ usocklnd_enqueue_tx(usock_conn_t *conn, usock_tx_t *tx,
                     int *send_immediately)
 {
         if (conn->uc_state == UC_READY &&
-            list_empty(&conn->uc_tx_list) &&
-            list_empty(&conn->uc_zcack_list) &&
+           list_empty(&conn->uc_tx_list) &&
+           list_empty(&conn->uc_zcack_list) &&
             !conn->uc_sending) {
                 conn->uc_sending = 1;
                 *send_immediately = 1;
@@ -792,7 +804,7 @@ usocklnd_enqueue_tx(usock_conn_t *conn, usock_tx_t *tx,
         }
 
         *send_immediately = 0;
-        list_add_tail(&tx->tx_list, &conn->uc_tx_list);
+       list_add_tail(&tx->tx_list, &conn->uc_tx_list);
 }
 
 /* Safely create new conn if needed. Save result in *connp.
@@ -850,6 +862,13 @@ usocklnd_find_or_create_conn(usock_peer_t *peer, int type,
 
         LASSERT(tx == NULL || zc_ack == NULL);
         if (tx != NULL) {
+                /* usocklnd_tear_peer_conn() could signal us stop queueing */
+                if (conn->uc_errored) {
+                        rc = -EIO;
+                        pthread_mutex_unlock(&conn->uc_lock);
+                        goto find_or_create_conn_failed;
+                }
+
                 usocklnd_enqueue_tx(conn, tx, send_immediately);
         } else {
                 rc = usocklnd_enqueue_zcack(conn, zc_ack);