* see the comment above rds_queue_reconnect()
*/
mutex_lock(&conn->c_cm_lock);
+ if (rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_DOWN) &&
+ (conn->c_laddr < conn->c_faddr)) {
+ rds_rtd(RDS_RTD_CM_EXT_P,
+ "incoming passive connection is trying to connect %p\n",
+ conn);
+ rds_conn_drop(conn, DR_IB_CONN_DROP_RACE);
+ goto out;
+ }
if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING)) {
/*
* in both of the cases below, the conn is half setup.
NIPQUAD(conn->c_laddr),
NIPQUAD(conn->c_faddr),
conn->c_tos);
+ rds_rtd(RDS_RTD_CM, "RDS/IB: connection "
+ " id %p conn %p "
+ "<%u.%u.%u.%u,%u.%u.%u.%u,%d> "
+ "racing for 15s, forcing reset\n",
+ cm_id, conn,
+ NIPQUAD(conn->c_laddr),
+ NIPQUAD(conn->c_faddr),
+ conn->c_tos);
rds_conn_drop(conn, DR_IB_REQ_WHILE_CONNECTING);
rds_ib_stats_inc(s_ib_listen_closed_stale);
} else {
/* Wait and see - our connect may still be succeeding */
+ rds_rtd(RDS_RTD_CM, "RDS/IB: connection "
+ " id %p conn %p "
+ "<%u.%u.%u.%u,%u.%u.%u.%u,%d> "
+ " will be rejected\n",
+ cm_id, conn,
+ NIPQUAD(conn->c_laddr),
+ NIPQUAD(conn->c_faddr),
+ conn->c_tos);
+ if (test_and_clear_bit(RDS_INITIAL_RECONNECT, &conn->c_flags) ||
+ (conn->c_laddr > conn->c_faddr) ||
+ rds_conn_self_loopback_passive(conn)) {
+ rds_rtd(RDS_RTD_CM, "RDS/IB: connection "
+ " id %p conn %p "
+ "<%u.%u.%u.%u,%u.%u.%u.%u,%d> "
+ " will be rejected as passive conn\n",
+ cm_id, conn,
+ NIPQUAD(conn->c_laddr),
+ NIPQUAD(conn->c_faddr),
+ conn->c_tos);
+ rds_conn_drop(conn, DR_IB_CONN_DROP_RACE);
+ }
rds_ib_stats_inc(s_ib_connect_raced);
}
}
*/
void rds_queue_reconnect(struct rds_conn_path *cp)
{
+ unsigned long delay = 0;
unsigned long rand;
struct rds_connection *conn = cp->cp_conn;
bool is_tcp = conn->c_trans->t_type == RDS_TRANS_TCP;
set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
if (cp->cp_reconnect_jiffies == 0) {
+ set_bit(RDS_INITIAL_RECONNECT, &cp->cp_flags);
cp->cp_reconnect_jiffies = rds_sysctl_reconnect_min_jiffies;
- queue_delayed_work(cp->cp_wq, &cp->cp_conn_w, 0);
+ queue_delayed_work(cp->cp_wq, &cp->cp_conn_w, rand % conn->c_reconnect_jiffies);
return;
}
- get_random_bytes(&rand, sizeof(rand));
+ clear_bit(RDS_INITIAL_RECONNECT, &conn->c_flags);
+ if ((conn->c_laddr > conn->c_faddr) ||
+ rds_conn_self_loopback_passive(conn))
+ delay = msecs_to_jiffies(15000);
rds_rtd(RDS_RTD_CM_EXT,
"%lu delay %lu ceil conn %p for %pI4 -> %pI4 tos %d\n",
- rand % cp->cp_reconnect_jiffies, cp->cp_reconnect_jiffies,
+ delay, cp->cp_reconnect_jiffies,
conn, &conn->c_laddr, &conn->c_faddr, conn->c_tos);
- queue_delayed_work(cp->cp_wq, &cp->cp_conn_w,
- rand % cp->cp_reconnect_jiffies);
-
+ queue_delayed_work(cp->cp_wq, &cp->cp_conn_w, delay);
cp->cp_reconnect_jiffies = min(cp->cp_reconnect_jiffies * 2,
rds_sysctl_reconnect_max_jiffies);
}