|
|
@@ -96,14 +96,16 @@ static struct rds_connection *rds_conn_lookup(struct net *net,
|
|
|
* and receiving over this connection again in the future. It is up to
|
|
|
* the transport to have serialized this call with its send and recv.
|
|
|
*/
|
|
|
-static void rds_conn_reset(struct rds_connection *conn)
|
|
|
+static void rds_conn_path_reset(struct rds_conn_path *cp)
|
|
|
{
|
|
|
+ struct rds_connection *conn = cp->cp_conn;
|
|
|
+
|
|
|
rdsdebug("connection %pI4 to %pI4 reset\n",
|
|
|
&conn->c_laddr, &conn->c_faddr);
|
|
|
|
|
|
rds_stats_inc(s_conn_reset);
|
|
|
- rds_send_reset(conn);
|
|
|
- conn->c_flags = 0;
|
|
|
+ rds_send_path_reset(cp);
|
|
|
+ cp->cp_flags = 0;
|
|
|
|
|
|
/* Do not clear next_rx_seq here, else we cannot distinguish
|
|
|
* retransmitted packets from new packets, and will hand all
|
|
|
@@ -294,10 +296,12 @@ struct rds_connection *rds_conn_create_outgoing(struct net *net,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(rds_conn_create_outgoing);
|
|
|
|
|
|
-void rds_conn_shutdown(struct rds_connection *conn)
|
|
|
+void rds_conn_shutdown(struct rds_conn_path *cp)
|
|
|
{
|
|
|
+ struct rds_connection *conn = cp->cp_conn;
|
|
|
+
|
|
|
/* shut it down unless it's down already */
|
|
|
- if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_DOWN)) {
|
|
|
+ if (!rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_DOWN)) {
|
|
|
/*
|
|
|
* Quiesce the connection mgmt handlers before we start tearing
|
|
|
* things down. We don't hold the mutex for the entire
|
|
|
@@ -305,35 +309,41 @@ void rds_conn_shutdown(struct rds_connection *conn)
|
|
|
* deadlocking with the CM handler. Instead, the CM event
|
|
|
* handler is supposed to check for state DISCONNECTING
|
|
|
*/
|
|
|
- mutex_lock(&conn->c_cm_lock);
|
|
|
- if (!rds_conn_transition(conn, RDS_CONN_UP, RDS_CONN_DISCONNECTING)
|
|
|
- && !rds_conn_transition(conn, RDS_CONN_ERROR, RDS_CONN_DISCONNECTING)) {
|
|
|
- rds_conn_error(conn, "shutdown called in state %d\n",
|
|
|
- atomic_read(&conn->c_state));
|
|
|
- mutex_unlock(&conn->c_cm_lock);
|
|
|
+ mutex_lock(&cp->cp_cm_lock);
|
|
|
+ if (!rds_conn_path_transition(cp, RDS_CONN_UP,
|
|
|
+ RDS_CONN_DISCONNECTING) &&
|
|
|
+ !rds_conn_path_transition(cp, RDS_CONN_ERROR,
|
|
|
+ RDS_CONN_DISCONNECTING)) {
|
|
|
+ rds_conn_path_error(cp,
|
|
|
+ "shutdown called in state %d\n",
|
|
|
+ atomic_read(&cp->cp_state));
|
|
|
+ mutex_unlock(&cp->cp_cm_lock);
|
|
|
return;
|
|
|
}
|
|
|
- mutex_unlock(&conn->c_cm_lock);
|
|
|
+ mutex_unlock(&cp->cp_cm_lock);
|
|
|
|
|
|
- wait_event(conn->c_waitq,
|
|
|
- !test_bit(RDS_IN_XMIT, &conn->c_flags));
|
|
|
- wait_event(conn->c_waitq,
|
|
|
- !test_bit(RDS_RECV_REFILL, &conn->c_flags));
|
|
|
+ wait_event(cp->cp_waitq,
|
|
|
+ !test_bit(RDS_IN_XMIT, &cp->cp_flags));
|
|
|
+ wait_event(cp->cp_waitq,
|
|
|
+ !test_bit(RDS_RECV_REFILL, &cp->cp_flags));
|
|
|
|
|
|
- conn->c_trans->conn_shutdown(conn);
|
|
|
- rds_conn_reset(conn);
|
|
|
+ if (!conn->c_trans->t_mp_capable)
|
|
|
+ conn->c_trans->conn_shutdown(conn);
|
|
|
+ else
|
|
|
+ conn->c_trans->conn_path_shutdown(cp);
|
|
|
+ rds_conn_path_reset(cp);
|
|
|
|
|
|
- if (!rds_conn_transition(conn, RDS_CONN_DISCONNECTING, RDS_CONN_DOWN)) {
|
|
|
+ if (!rds_conn_path_transition(cp, RDS_CONN_DISCONNECTING,
|
|
|
+ RDS_CONN_DOWN)) {
|
|
|
/* This can happen - eg when we're in the middle of tearing
|
|
|
* down the connection, and someone unloads the rds module.
|
|
|
* Quite reproduceable with loopback connections.
|
|
|
* Mostly harmless.
|
|
|
*/
|
|
|
- rds_conn_error(conn,
|
|
|
- "%s: failed to transition to state DOWN, "
|
|
|
- "current state is %d\n",
|
|
|
- __func__,
|
|
|
- atomic_read(&conn->c_state));
|
|
|
+ rds_conn_path_error(cp, "%s: failed to transition "
|
|
|
+ "to state DOWN, current state "
|
|
|
+ "is %d\n", __func__,
|
|
|
+ atomic_read(&cp->cp_state));
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
@@ -342,13 +352,13 @@ void rds_conn_shutdown(struct rds_connection *conn)
|
|
|
* The passive side of an IB loopback connection is never added
|
|
|
* to the conn hash, so we never trigger a reconnect on this
|
|
|
* conn - the reconnect is always triggered by the active peer. */
|
|
|
- cancel_delayed_work_sync(&conn->c_conn_w);
|
|
|
+ cancel_delayed_work_sync(&cp->cp_conn_w);
|
|
|
rcu_read_lock();
|
|
|
if (!hlist_unhashed(&conn->c_hash_node)) {
|
|
|
rcu_read_unlock();
|
|
|
if (conn->c_trans->t_type != RDS_TRANS_TCP ||
|
|
|
- conn->c_path[0].cp_outgoing == 1)
|
|
|
- rds_queue_reconnect(&conn->c_path[0]);
|
|
|
+ cp->cp_outgoing == 1)
|
|
|
+ rds_queue_reconnect(cp);
|
|
|
} else {
|
|
|
rcu_read_unlock();
|
|
|
}
|