if (conn->ibc_state != IBLND_CONN_INIT) {
kib_net_t *net = peer->ibp_ni->ni_data;
- kiblnd_peer_decref(peer);
rdma_destroy_id(cmid);
atomic_dec(&net->ibn_nconns);
+ if (conn->ibc_conn_race) {
+ if (peer->ibp_accepting == 0 &&
+ !list_empty(&peer->ibp_tx_queue)) {
+ kiblnd_connect_peer(peer);
+ } else {
+ rwlock_t *glock = &kiblnd_data.kib_global_lock;
+ unsigned long flags;
+
+ write_lock_irqsave(glock, flags);
+ peer->ibp_connecting--;
+ write_unlock_irqrestore(glock, flags);
+ }
+ }
+ kiblnd_peer_decref(peer);
}
LIBCFS_FREE(conn, sizeof(*conn));
/* set on comms error */
int ibc_comms_error;
/* receive buffers owned */
- unsigned int ibc_nrx:16;
+ unsigned short ibc_nrx;
+ /** rejected by connection race */
+ unsigned short ibc_conn_race:1;
/* scheduled for attention */
- unsigned int ibc_scheduled:1;
+ unsigned short ibc_scheduled:1;
/* CQ callback fired */
- unsigned int ibc_ready:1;
+ unsigned short ibc_ready:1;
/* time of last send */
unsigned long ibc_last_send;
/** link chain for kiblnd_check_conns only */
int kiblnd_dev_failover(kib_dev_t *dev);
int kiblnd_create_peer (lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid);
void kiblnd_destroy_peer (kib_peer_t *peer);
+void kiblnd_connect_peer(kib_peer_t *peer);
void kiblnd_destroy_dev (kib_dev_t *dev);
void kiblnd_unlink_peer_locked (kib_peer_t *peer);
kib_peer_t *kiblnd_find_peer_locked (lnet_nid_t nid);
return rc;
}
-static void
+void
kiblnd_connect_peer (kib_peer_t *peer)
{
struct rdma_cm_id *cmid;
kiblnd_reconnect (kib_conn_t *conn, int version,
__u64 incarnation, int why, kib_connparams_t *cp)
{
- kib_peer_t *peer = conn->ibc_peer;
- char *reason;
- int retry = 0;
- unsigned long flags;
+ kib_peer_t *peer = conn->ibc_peer;
+ char *reason;
+ int retry_now = 0;
+ unsigned long flags;
LASSERT (conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT);
LASSERT (peer->ibp_connecting > 0); /* 'conn' at least */
peer->ibp_version != version) &&
peer->ibp_connecting == 1 &&
peer->ibp_accepting == 0) {
- retry = 1;
+ if (why == IBLND_REJECT_CONN_RACE) {
+ /* don't reconnect immediately, intensive reconnecting
+ * may consume a lot of memory. kiblnd_destroy_conn
+ * will reconnect after releasing all resources of
+ * this connection */
+ conn->ibc_conn_race = 1;
+ } else {
+ retry_now = 1;
+ }
peer->ibp_connecting++;
peer->ibp_version = version;
write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags);
- if (!retry)
+ if (!retry_now)
return;
switch (why) {
reason = "stale";
break;
- case IBLND_REJECT_CONN_RACE:
- reason = "conn race";
- break;
-
case IBLND_REJECT_CONN_UNCOMPAT:
reason = "version negotiation";
break;