/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2005 Cluster File Systems, Inc. All rights reserved.
- * Author: Eric Barton <eeb@bartonsoftware.com>
+ * GPL HEADER START
*
- * This file is part of the Lustre file system, http://www.lustre.org
- * Lustre is a trademark of Cluster File Systems, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
- * This file is confidential source code owned by Cluster File Systems.
- * No viewing, modification, compilation, redistribution, or any other
- * form of use is permitted except through a signed license agreement.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
*
- * If you have not signed such an agreement, then you have no rights to
- * this file. Please destroy it immediately and contact CFS.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
*
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lnet/ulnds/ptllnd/ptllnd_cb.c
+ *
+ * Author: Eric Barton <eeb@bartonsoftware.com>
*/
#include "ptllnd.h"
{
ptllnd_peer_t *peer = tx->tx_peer;
+ LASSERT (tx->tx_type != PTLLND_MSG_TYPE_NOOP);
+
ptllnd_set_tx_deadline(tx);
- list_add_tail(&tx->tx_list, &peer->plp_txq);
+ cfs_list_add_tail(&tx->tx_list, &peer->plp_txq);
ptllnd_check_sends(peer);
}
static int idx = 0;
char *str = strs[idx++];
-
+
if (idx >= sizeof(strs)/sizeof(strs[0]))
idx = 0;
LASSERT (peer->plp_closing);
LASSERT (plni->plni_npeers > 0);
- LASSERT (list_empty(&peer->plp_txq));
- LASSERT (list_empty(&peer->plp_activeq));
+ LASSERT (cfs_list_empty(&peer->plp_txq));
+ LASSERT (cfs_list_empty(&peer->plp_noopq));
+ LASSERT (cfs_list_empty(&peer->plp_activeq));
plni->plni_npeers--;
LIBCFS_FREE(peer, sizeof(*peer));
}
void
-ptllnd_abort_txs(ptllnd_ni_t *plni, struct list_head *q)
+ptllnd_abort_txs(ptllnd_ni_t *plni, cfs_list_t *q)
{
- while (!list_empty(q)) {
- ptllnd_tx_t *tx = list_entry(q->next, ptllnd_tx_t, tx_list);
+ while (!cfs_list_empty(q)) {
+ ptllnd_tx_t *tx = cfs_list_entry(q->next, ptllnd_tx_t, tx_list);
tx->tx_status = -ESHUTDOWN;
- list_del(&tx->tx_list);
- list_add_tail(&tx->tx_list, &plni->plni_zombie_txs);
+ cfs_list_del(&tx->tx_list);
+ cfs_list_add_tail(&tx->tx_list, &plni->plni_zombie_txs);
}
}
peer->plp_closing = 1;
- if (!list_empty(&peer->plp_txq) ||
- !list_empty(&peer->plp_activeq) ||
+ if (!cfs_list_empty(&peer->plp_txq) ||
+ !cfs_list_empty(&peer->plp_noopq) ||
+ !cfs_list_empty(&peer->plp_activeq) ||
error != 0) {
- CWARN("Closing %s\n", libcfs_id2str(peer->plp_id));
+ CWARN("Closing %s: %d\n", libcfs_id2str(peer->plp_id), error);
if (plni->plni_debug)
ptllnd_dump_debug(ni, peer->plp_id);
}
-
+
ptllnd_abort_txs(plni, &peer->plp_txq);
+ ptllnd_abort_txs(plni, &peer->plp_noopq);
ptllnd_abort_txs(plni, &peer->plp_activeq);
- list_del(&peer->plp_list);
+ cfs_list_del(&peer->plp_list);
ptllnd_peer_decref(peer);
}
{
ptllnd_ni_t *plni = ni->ni_data;
unsigned int hash = LNET_NIDADDR(id.nid) % plni->plni_peer_hash_size;
- struct list_head *tmp;
ptllnd_peer_t *plp;
ptllnd_tx_t *tx;
int rc;
LASSERT (LNET_NIDNET(id.nid) == LNET_NIDNET(ni->ni_nid));
- list_for_each(tmp, &plni->plni_peer_hash[hash]) {
- plp = list_entry(tmp, ptllnd_peer_t, plp_list);
-
+ cfs_list_for_each_entry (plp, &plni->plni_peer_hash[hash], plp_list) {
if (plp->plp_id.nid == id.nid &&
plp->plp_id.pid == id.pid) {
ptllnd_peer_addref(plp);
plp->plp_extra_lazy_credits = 0;
plp->plp_match = 0;
plp->plp_stamp = 0;
+ plp->plp_sent_hello = 0;
plp->plp_recvd_hello = 0;
plp->plp_closing = 0;
plp->plp_refcount = 1;
CFS_INIT_LIST_HEAD(&plp->plp_list);
CFS_INIT_LIST_HEAD(&plp->plp_txq);
+ CFS_INIT_LIST_HEAD(&plp->plp_noopq);
CFS_INIT_LIST_HEAD(&plp->plp_activeq);
ptllnd_peer_addref(plp);
- list_add_tail(&plp->plp_list, &plni->plni_peer_hash[hash]);
+ cfs_list_add_tail(&plp->plp_list, &plni->plni_peer_hash[hash]);
tx = ptllnd_new_tx(plp, PTLLND_MSG_TYPE_HELLO, 0);
if (tx == NULL) {
}
int
-ptllnd_count_q(struct list_head *q)
+ptllnd_count_q(cfs_list_t *q)
{
- struct list_head *e;
- int n = 0;
-
- list_for_each(e, q) {
+ cfs_list_t *e;
+ int n = 0;
+
+ cfs_list_for_each(e, q) {
n++;
}
-
+
return n;
}
const char *
-ptllnd_tx_typestr(int type)
+ptllnd_tx_typestr(int type)
{
switch (type) {
case PTLLND_RDMA_WRITE:
return "rdma_write";
-
+
case PTLLND_RDMA_READ:
return "rdma_read";
case PTLLND_MSG_TYPE_PUT:
return "put_req";
-
+
case PTLLND_MSG_TYPE_GET:
return "get_req";
}
void
-ptllnd_debug_tx(ptllnd_tx_t *tx)
+ptllnd_debug_tx(ptllnd_tx_t *tx)
{
CDEBUG(D_WARNING, "%s %s b %ld.%06ld/%ld.%06ld"
" r %ld.%06ld/%ld.%06ld status %d\n",
ptllnd_tx_typestr(tx->tx_type),
libcfs_id2str(tx->tx_peer->plp_id),
- tx->tx_bulk_posted.tv_sec, tx->tx_bulk_posted.tv_usec,
+ tx->tx_bulk_posted.tv_sec, tx->tx_bulk_posted.tv_usec,
tx->tx_bulk_done.tv_sec, tx->tx_bulk_done.tv_usec,
tx->tx_req_posted.tv_sec, tx->tx_req_posted.tv_usec,
tx->tx_req_done.tv_sec, tx->tx_req_done.tv_usec,
ptllnd_debug_peer(lnet_ni_t *ni, lnet_process_id_t id)
{
ptllnd_peer_t *plp = ptllnd_find_peer(ni, id, 0);
- struct list_head *tmp;
ptllnd_ni_t *plni = ni->ni_data;
ptllnd_tx_t *tx;
-
+
if (plp == NULL) {
CDEBUG(D_WARNING, "No peer %s\n", libcfs_id2str(id));
return;
}
-
- CDEBUG(D_WARNING, "%s %s%s [%d] "LPU64".%06d m "LPU64" q %d/%d c %d/%d+%d(%d)\n",
- libcfs_id2str(id),
- plp->plp_recvd_hello ? "H" : "_",
- plp->plp_closing ? "C" : "_",
- plp->plp_refcount,
- plp->plp_stamp / 1000000, (int)(plp->plp_stamp % 1000000),
- plp->plp_match,
- ptllnd_count_q(&plp->plp_txq),
- ptllnd_count_q(&plp->plp_activeq),
- plp->plp_credits, plp->plp_outstanding_credits, plp->plp_sent_credits,
- plni->plni_peer_credits + plp->plp_lazy_credits);
+
+ CWARN("%s %s%s [%d] "LPU64".%06d m "LPU64" q %d/%d/%d c %d/%d+%d(%d)\n",
+ libcfs_id2str(id),
+ plp->plp_recvd_hello ? "H" : "_",
+ plp->plp_closing ? "C" : "_",
+ plp->plp_refcount,
+ plp->plp_stamp / 1000000, (int)(plp->plp_stamp % 1000000),
+ plp->plp_match,
+ ptllnd_count_q(&plp->plp_txq),
+ ptllnd_count_q(&plp->plp_noopq),
+ ptllnd_count_q(&plp->plp_activeq),
+ plp->plp_credits, plp->plp_outstanding_credits, plp->plp_sent_credits,
+ plni->plni_peer_credits + plp->plp_lazy_credits);
CDEBUG(D_WARNING, "txq:\n");
- list_for_each (tmp, &plp->plp_txq) {
- tx = list_entry(tmp, ptllnd_tx_t, tx_list);
-
+ cfs_list_for_each_entry (tx, &plp->plp_txq, tx_list) {
+ ptllnd_debug_tx(tx);
+ }
+
+ CDEBUG(D_WARNING, "noopq:\n");
+ cfs_list_for_each_entry (tx, &plp->plp_noopq, tx_list) {
ptllnd_debug_tx(tx);
}
CDEBUG(D_WARNING, "activeq:\n");
- list_for_each (tmp, &plp->plp_activeq) {
- tx = list_entry(tmp, ptllnd_tx_t, tx_list);
-
+ cfs_list_for_each_entry (tx, &plp->plp_activeq, tx_list) {
ptllnd_debug_tx(tx);
}
CDEBUG(D_WARNING, "zombies:\n");
- list_for_each (tmp, &plni->plni_zombie_txs) {
- tx = list_entry(tmp, ptllnd_tx_t, tx_list);
-
+ cfs_list_for_each_entry (tx, &plni->plni_zombie_txs, tx_list) {
if (tx->tx_peer->plp_id.nid == id.nid &&
tx->tx_peer->plp_id.pid == id.pid)
ptllnd_debug_tx(tx);
}
-
+
CDEBUG(D_WARNING, "history:\n");
- list_for_each (tmp, &plni->plni_tx_history) {
- tx = list_entry(tmp, ptllnd_tx_t, tx_list);
-
+ cfs_list_for_each_entry (tx, &plni->plni_tx_history, tx_list) {
if (tx->tx_peer->plp_id.nid == id.nid &&
tx->tx_peer->plp_id.pid == id.pid)
ptllnd_debug_tx(tx);
}
-
+
ptllnd_peer_decref(plp);
}
ptllnd_dump_history();
}
-void
-ptllnd_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive)
-{
- lnet_process_id_t id;
- ptllnd_peer_t *peer;
- time_t start = cfs_time_current_sec();
- ptllnd_ni_t *plni = ni->ni_data;
- int w = plni->plni_long_wait;
-
- /* This is only actually used to connect to routers at startup! */
- LASSERT(alive);
-
- id.nid = nid;
- id.pid = LUSTRE_SRV_LNET_PID;
-
- peer = ptllnd_find_peer(ni, id, 1);
- if (peer == NULL)
- return;
-
- /* wait for the peer to reply */
- while (!peer->plp_recvd_hello) {
- if (w > 0 && cfs_time_current_sec() > start + w/1000) {
- CWARN("Waited %ds to connect to %s\n",
- (int)(cfs_time_current_sec() - start),
- libcfs_id2str(id));
- w *= 2;
- }
-
- ptllnd_wait(ni, w);
- }
-
- ptllnd_peer_decref(peer);
-}
-
int
ptllnd_setasync(lnet_ni_t *ni, lnet_process_id_t id, int nasync)
{
ptllnd_peer_t *peer = ptllnd_find_peer(ni, id, nasync > 0);
int rc;
-
+
if (peer == NULL)
return -ENOMEM;
nasync -= peer->plp_extra_lazy_credits;
peer->plp_extra_lazy_credits = 0;
-
+
rc = ptllnd_size_buffers(ni, nasync);
if (rc == 0) {
peer->plp_lazy_credits += nasync;
ptllnd_peer_addref(peer);
plni->plni_ntxs++;
- CDEBUG(D_NET, "tx=%p\n",tx);
+ CDEBUG(D_NET, "tx=%p\n", tx);
return tx;
}
int max = plni->plni_max_tx_history;
while (plni->plni_ntx_history > max) {
- ptllnd_tx_t *tx = list_entry(plni->plni_tx_history.next,
- ptllnd_tx_t, tx_list);
- list_del(&tx->tx_list);
+ ptllnd_tx_t *tx = cfs_list_entry(plni->plni_tx_history.next,
+ ptllnd_tx_t, tx_list);
+ cfs_list_del(&tx->tx_list);
ptllnd_peer_decref(tx->tx_peer);
tx->tx_completing = 1;
- if (!list_empty(&tx->tx_list))
- list_del_init(&tx->tx_list);
+ if (!cfs_list_empty(&tx->tx_list))
+ cfs_list_del_init(&tx->tx_list);
if (tx->tx_status != 0) {
if (plni->plni_debug) {
}
ptllnd_close_peer(peer, tx->tx_status);
}
-
+
ptllnd_abort_tx(tx, &tx->tx_reqmdh);
ptllnd_abort_tx(tx, &tx->tx_bulkmdh);
}
plni->plni_ntx_history++;
- list_add_tail(&tx->tx_list, &plni->plni_tx_history);
-
+ cfs_list_add_tail(&tx->tx_list, &plni->plni_tx_history);
+
ptllnd_cull_tx_history(plni);
}
piov[npiov].iov_base = iov[npiov].iov_base + temp_offset;
piov[npiov].iov_len = iov[npiov].iov_len - temp_offset;
-
+
if (piov[npiov].iov_len >= resid) {
piov[npiov].iov_len = resid;
npiov++;
return -ENOMEM;
}
+static inline int
+ptllnd_peer_send_noop (ptllnd_peer_t *peer)
+{
+ ptllnd_ni_t *plni = peer->plp_ni->ni_data;
+
+ if (!peer->plp_sent_hello ||
+ peer->plp_credits == 0 ||
+ !cfs_list_empty(&peer->plp_noopq) ||
+ peer->plp_outstanding_credits < PTLLND_CREDIT_HIGHWATER(plni))
+ return 0;
+
+ /* No tx to piggyback NOOP onto or no credit to send a tx */
+ return (cfs_list_empty(&peer->plp_txq) || peer->plp_credits == 1);
+}
+
void
ptllnd_check_sends(ptllnd_peer_t *peer)
{
- lnet_ni_t *ni = peer->plp_ni;
- ptllnd_ni_t *plni = ni->ni_data;
+ ptllnd_ni_t *plni = peer->plp_ni->ni_data;
ptllnd_tx_t *tx;
ptl_md_t md;
ptl_handle_md_t mdh;
peer->plp_outstanding_credits, peer->plp_sent_credits,
plni->plni_peer_credits + peer->plp_lazy_credits);
- if (list_empty(&peer->plp_txq) &&
- peer->plp_outstanding_credits >= PTLLND_CREDIT_HIGHWATER(plni) &&
- peer->plp_credits != 0) {
-
+ if (ptllnd_peer_send_noop(peer)) {
tx = ptllnd_new_tx(peer, PTLLND_MSG_TYPE_NOOP, 0);
CDEBUG(D_NET, "NOOP tx=%p\n",tx);
if (tx == NULL) {
CERROR("Can't return credits to %s\n",
libcfs_id2str(peer->plp_id));
} else {
- list_add_tail(&tx->tx_list, &peer->plp_txq);
+ ptllnd_set_tx_deadline(tx);
+ cfs_list_add_tail(&tx->tx_list, &peer->plp_noopq);
}
}
- while (!list_empty(&peer->plp_txq)) {
- tx = list_entry(peer->plp_txq.next, ptllnd_tx_t, tx_list);
+ for (;;) {
+ if (!cfs_list_empty(&peer->plp_noopq)) {
+ LASSERT (peer->plp_sent_hello);
+ tx = cfs_list_entry(peer->plp_noopq.next,
+ ptllnd_tx_t, tx_list);
+ } else if (!cfs_list_empty(&peer->plp_txq)) {
+ tx = cfs_list_entry(peer->plp_txq.next,
+ ptllnd_tx_t, tx_list);
+ } else {
+ /* nothing to send right now */
+ break;
+ }
LASSERT (tx->tx_msgsize > 0);
<= plni->plni_peer_credits + peer->plp_lazy_credits);
LASSERT (peer->plp_credits >= 0);
+ /* say HELLO first */
+ if (!peer->plp_sent_hello) {
+ LASSERT (cfs_list_empty(&peer->plp_noopq));
+ LASSERT (tx->tx_type == PTLLND_MSG_TYPE_HELLO);
+
+ peer->plp_sent_hello = 1;
+ }
+
if (peer->plp_credits == 0) { /* no credits */
PTLLND_HISTORY("%s[%d/%d+%d(%d)]: no creds for %p",
libcfs_id2str(peer->plp_id),
peer->plp_lazy_credits, tx);
break;
}
-
- if (peer->plp_credits == 1 && /* last credit reserved for */
- peer->plp_outstanding_credits == 0) { /* returning credits */
+
+ /* Last/Initial credit reserved for NOOP/HELLO */
+ if (peer->plp_credits == 1 &&
+ tx->tx_type != PTLLND_MSG_TYPE_NOOP &&
+ tx->tx_type != PTLLND_MSG_TYPE_HELLO) {
PTLLND_HISTORY("%s[%d/%d+%d(%d)]: too few creds for %p",
libcfs_id2str(peer->plp_id),
peer->plp_credits,
peer->plp_lazy_credits, tx);
break;
}
-
- list_del(&tx->tx_list);
- list_add_tail(&tx->tx_list, &peer->plp_activeq);
+
+ cfs_list_del(&tx->tx_list);
+ cfs_list_add_tail(&tx->tx_list, &peer->plp_activeq);
CDEBUG(D_NET, "Sending at TX=%p type=%s (%d)\n",tx,
- ptllnd_msgtype2str(tx->tx_type),tx->tx_type);
+ ptllnd_msgtype2str(tx->tx_type),tx->tx_type);
if (tx->tx_type == PTLLND_MSG_TYPE_NOOP &&
- (!list_empty(&peer->plp_txq) ||
- peer->plp_outstanding_credits <
- PTLLND_CREDIT_HIGHWATER(plni))) {
+ !ptllnd_peer_send_noop(peer)) {
/* redundant NOOP */
ptllnd_tx_done(tx);
continue;
/*
* Return all the credits we have
*/
- tx->tx_msg.ptlm_credits = peer->plp_outstanding_credits;
- peer->plp_sent_credits += peer->plp_outstanding_credits;
- peer->plp_outstanding_credits = 0;
+ tx->tx_msg.ptlm_credits = MIN(PTLLND_MSG_MAX_CREDITS,
+ peer->plp_outstanding_credits);
+ peer->plp_sent_credits += tx->tx_msg.ptlm_credits;
+ peer->plp_outstanding_credits -= tx->tx_msg.ptlm_credits;
/*
* One less credit
LASSERT (tx->tx_type != PTLLND_RDMA_WRITE &&
tx->tx_type != PTLLND_RDMA_READ);
-
+
tx->tx_reqmdh = mdh;
gettimeofday(&tx->tx_req_posted, NULL);
if (tx == NULL) {
CERROR("Can't allocate %s tx for %s\n",
- type == PTLLND_MSG_TYPE_GET ? "GET" : "PUT/REPLY",
- libcfs_id2str(peer->plp_id));
+ ptllnd_msgtype2str(type), libcfs_id2str(peer->plp_id));
return -ENOMEM;
}
rc = ptllnd_set_txiov(tx, niov, iov, offset, len);
if (rc != 0) {
- CERROR ("Can't allocate iov %d for %s\n",
- niov, libcfs_id2str(peer->plp_id));
+ CERROR("Can't allocate iov %d for %s\n",
+ niov, libcfs_id2str(peer->plp_id));
rc = -ENOMEM;
goto failed;
}
start = cfs_time_current_sec();
w = plni->plni_long_wait;
+ ptllnd_set_tx_deadline(tx);
- while (!peer->plp_recvd_hello) { /* wait to validate plp_match */
+ while (!peer->plp_recvd_hello) { /* wait to validate plp_match */
if (peer->plp_closing) {
rc = -EIO;
goto failed;
}
+
+ /* NB must check here to avoid unbounded wait - tx not yet
+ * on peer->plp_txq, so ptllnd_watchdog can't expire it */
+ if (tx->tx_deadline < cfs_time_current_sec()) {
+ CERROR("%s tx for %s timed out\n",
+ ptllnd_msgtype2str(type),
+ libcfs_id2str(peer->plp_id));
+ rc = -ETIMEDOUT;
+ goto failed;
+ }
+
if (w > 0 && cfs_time_current_sec() > start + w/1000) {
CWARN("Waited %ds to connect to %s\n",
(int)(cfs_time_current_sec() - start),
return 0;
failed:
+ tx->tx_status = rc;
ptllnd_tx_done(tx);
return rc;
}
rc = ptllnd_set_txiov(tx, niov, iov, offset, len);
if (rc != 0) {
- CERROR ("Can't allocate iov %d for %s\n",
- niov, libcfs_id2str(peer->plp_id));
+ CERROR("Can't allocate iov %d for %s\n",
+ niov, libcfs_id2str(peer->plp_id));
rc = -ENOMEM;
goto failed;
}
tx->tx_lnetmsg = msg;
ptllnd_set_tx_deadline(tx);
- list_add_tail(&tx->tx_list, &peer->plp_activeq);
+ cfs_list_add_tail(&tx->tx_list, &peer->plp_activeq);
gettimeofday(&tx->tx_bulk_posted, NULL);
if (type == PTLLND_RDMA_READ)
LASSERT (msg->msg_niov <= PTL_MD_MAX_IOV); /* !!! */
- CDEBUG(D_NET, "%s [%d]+%d,%d -> %s%s\n",
+ CDEBUG(D_NET, "%s [%d]+%d,%d -> %s%s\n",
lnet_msgtyp2str(msg->msg_type),
msg->msg_niov, msg->msg_offset, msg->msg_len,
libcfs_nid2str(msg->msg_target.nid),
libcfs_id2str(msg->msg_target));
return -EHOSTUNREACH;
}
-
+
plp = ptllnd_find_peer(ni, msg->msg_target, 1);
if (plp == NULL)
return -ENOMEM;
ptllnd_rx_done(ptllnd_rx_t *rx)
{
ptllnd_peer_t *plp = rx->rx_peer;
- lnet_ni_t *ni = plp->plp_ni;
- ptllnd_ni_t *plni = ni->ni_data;
+ ptllnd_ni_t *plni = plp->plp_ni->ni_data;
plp->plp_outstanding_credits++;
plp->plp_sent_credits,
plni->plni_peer_credits + plp->plp_lazy_credits, rx);
- ptllnd_check_sends(rx->rx_peer);
+ ptllnd_check_sends(plp);
LASSERT (plni->plni_nrxs > 0);
plni->plni_nrxs--;
msg_version = flip ? __swab16(msg->ptlm_version) : msg->ptlm_version;
if (msg_version != PTLLND_MSG_VERSION) {
- CERROR("Bad protocol version %04x from %s: %04x expected\n",
+ CERROR("Bad protocol version %04x from %s: %04x expected\n",
(__u32)msg_version, ptllnd_ptlid2str(initiator), PTLLND_MSG_VERSION);
if (plni->plni_abort_on_protocol_mismatch)
msg->ptlm_version = msg_version;
msg->ptlm_cksum = msg_cksum;
-
+
if (flip) {
/* NB stamps are opaque cookies */
__swab32s(&msg->ptlm_nob);
__swab32s(&msg->ptlm_srcpid);
__swab32s(&msg->ptlm_dstpid);
}
-
+
srcid.nid = msg->ptlm_srcnid;
srcid.pid = msg->ptlm_srcpid;
}
if (msg->ptlm_type == PTLLND_MSG_TYPE_NAK) {
- CERROR("NAK from %s (%s)\n",
+ CERROR("NAK from %s (%s)\n",
libcfs_id2str(srcid),
ptllnd_ptlid2str(initiator));
if (plni->plni_dump_on_nak)
ptllnd_dump_debug(ni, srcid);
-
+
if (plni->plni_abort_on_nak)
abort();
-
+
+ plp = ptllnd_find_peer(ni, srcid, 0);
+ if (plp == NULL) {
+ CERROR("Ignore NAK from %s: no peer\n", libcfs_id2str(srcid));
+ return;
+ }
+ ptllnd_close_peer(plp, -EPROTO);
+ ptllnd_peer_decref(plp);
return;
}
-
+
if (msg->ptlm_dstnid != ni->ni_nid ||
msg->ptlm_dstpid != the_lnet.ln_pid) {
CERROR("Bad dstid %s (%s expected) from %s\n",
__swab32s(&msg->ptlm_u.hello.kptlhm_max_msg_size);
}
break;
-
+
case PTLLND_MSG_TYPE_NOOP:
break;
if (plp->plp_sent_credits == 0) {
CERROR("%s[%d/%d+%d(%d)]: unexpected message\n",
libcfs_id2str(plp->plp_id),
- plp->plp_credits, plp->plp_outstanding_credits,
+ plp->plp_credits, plp->plp_outstanding_credits,
plp->plp_sent_credits,
plni->plni_peer_credits + plp->plp_lazy_credits);
return;
}
plp->plp_sent_credits--;
-
+
/* No check for credit overflow - the peer may post new buffers after
* the startup handshake. */
- if (msg->ptlm_credits > 0) {
- plp->plp_credits += msg->ptlm_credits;
- ptllnd_check_sends(plp);
- }
+ plp->plp_credits += msg->ptlm_credits;
/* All OK so far; assume the message is good... */
break;
}
+ if (msg->ptlm_credits > 0)
+ ptllnd_check_sends(plp);
+
ptllnd_peer_decref(plp);
}
/* Portals can't force message alignment - someone sending an
* odd-length message could misalign subsequent messages */
if ((event->mlength & 7) != 0) {
- CERROR("Message from %s has odd length %llu: "
- "probable version incompatibility\n",
+ CERROR("Message from %s has odd length "LPU64
+ " probable version incompatibility\n",
ptllnd_ptlid2str(event->initiator),
event->mlength);
LBUG();
LASSERT (!isreq != !isbulk); /* always one and only 1 match */
PTLLND_HISTORY("%s[%d/%d+%d(%d)]: TX done %p %s%s",
- libcfs_id2str(tx->tx_peer->plp_id),
+ libcfs_id2str(tx->tx_peer->plp_id),
tx->tx_peer->plp_credits,
tx->tx_peer->plp_outstanding_credits,
tx->tx_peer->plp_sent_credits,
PtlHandleIsEqual(tx->tx_reqmdh, PTL_INVALID_HANDLE))) {
if (error)
tx->tx_status = -EIO;
- list_del(&tx->tx_list);
- list_add_tail(&tx->tx_list, &plni->plni_zombie_txs);
+ cfs_list_del(&tx->tx_list);
+ cfs_list_add_tail(&tx->tx_list, &plni->plni_zombie_txs);
}
}
ptllnd_find_timed_out_tx(ptllnd_peer_t *peer)
{
time_t now = cfs_time_current_sec();
- struct list_head *tmp;
+ ptllnd_tx_t *tx;
- list_for_each(tmp, &peer->plp_txq) {
- ptllnd_tx_t *tx = list_entry(tmp, ptllnd_tx_t, tx_list);
-
+ cfs_list_for_each_entry (tx, &peer->plp_txq, tx_list) {
if (tx->tx_deadline < now)
return tx;
}
-
- list_for_each(tmp, &peer->plp_activeq) {
- ptllnd_tx_t *tx = list_entry(tmp, ptllnd_tx_t, tx_list);
-
+
+ cfs_list_for_each_entry (tx, &peer->plp_noopq, tx_list) {
+ if (tx->tx_deadline < now)
+ return tx;
+ }
+
+ cfs_list_for_each_entry (tx, &peer->plp_activeq, tx_list) {
if (tx->tx_deadline < now)
return tx;
}
ptllnd_check_peer(ptllnd_peer_t *peer)
{
ptllnd_tx_t *tx = ptllnd_find_timed_out_tx(peer);
-
+
if (tx == NULL)
return;
-
- CERROR("%s: timed out\n", libcfs_id2str(peer->plp_id));
+
+ CERROR("%s (sent %d recvd %d, credits %d/%d/%d/%d/%d): timed out %p %p\n",
+ libcfs_id2str(peer->plp_id), peer->plp_sent_hello, peer->plp_recvd_hello,
+ peer->plp_credits, peer->plp_outstanding_credits,
+ peer->plp_sent_credits, peer->plp_lazy_credits,
+ peer->plp_extra_lazy_credits, tx, tx->tx_lnetmsg);
+ ptllnd_debug_tx(tx);
ptllnd_close_peer(peer, -ETIMEDOUT);
}
int chunk = plni->plni_peer_hash_size;
int interval = now - (plni->plni_watchdog_nextt - p);
int i;
- struct list_head *hashlist;
- struct list_head *tmp;
- struct list_head *nxt;
+ cfs_list_t *hashlist;
+ cfs_list_t *tmp;
+ cfs_list_t *nxt;
- /* Time to check for RDMA timeouts on a few more peers:
+ /* Time to check for RDMA timeouts on a few more peers:
* I try to do checks every 'p' seconds on a proportion of the peer
* table and I need to check every connection 'n' times within a
* timeout interval, to ensure I detect a timeout on any connection
for (i = 0; i < chunk; i++) {
hashlist = &plni->plni_peer_hash[plni->plni_watchdog_peeridx];
-
- list_for_each_safe(tmp, nxt, hashlist) {
- ptllnd_check_peer(list_entry(tmp, ptllnd_peer_t, plp_list));
+
+ cfs_list_for_each_safe(tmp, nxt, hashlist) {
+ ptllnd_check_peer(cfs_list_entry(tmp, ptllnd_peer_t,
+ plp_list));
}
-
+
plni->plni_watchdog_peeridx = (plni->plni_watchdog_peeridx + 1) %
plni->plni_peer_hash_size;
}
struct timeval then;
struct timeval now;
struct timeval deadline;
-
+
ptllnd_ni_t *plni = ni->ni_data;
ptllnd_tx_t *tx;
ptl_event_t event;
for (;;) {
gettimeofday(&then, NULL);
-
+
rc = PtlEQPoll(&plni->plni_eqh, 1, timeout, &event, &which);
gettimeofday(&now, NULL);
ptllnd_watchdog(ni, now.tv_sec);
LASSERT (now.tv_sec < plni->plni_watchdog_nextt);
}
-
+
if (now.tv_sec > deadline.tv_sec || /* timeout expired */
(now.tv_sec == deadline.tv_sec &&
now.tv_usec >= deadline.tv_usec))
continue;
}
-
+
LASSERT (rc == PTL_OK || rc == PTL_EQ_DROPPED);
if (rc == PTL_EQ_DROPPED)
}
}
- while (!list_empty(&plni->plni_zombie_txs)) {
- tx = list_entry(plni->plni_zombie_txs.next,
+ while (!cfs_list_empty(&plni->plni_zombie_txs)) {
+ tx = cfs_list_entry(plni->plni_zombie_txs.next,
ptllnd_tx_t, tx_list);
- list_del_init(&tx->tx_list);
+ cfs_list_del_init(&tx->tx_list);
ptllnd_tx_done(tx);
}