-/* -*- 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/
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;
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;
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);
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);
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)
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;
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;
{
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);
}
{
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));
}
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);
}
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;
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);
/* 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;
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);
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;
}
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;
}
*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.
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);