RDS: Update rds_conn_shutdown to work with rds_conn_path
This commit changes rds_conn_shutdown to take a rds_conn_path * argument, allowing it to shutdown paths other than c_path[0] for MP-capable transports. Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
1c5113cf79
Коммит
d769ef81d5
|
@ -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
|
* 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.
|
* 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",
|
rdsdebug("connection %pI4 to %pI4 reset\n",
|
||||||
&conn->c_laddr, &conn->c_faddr);
|
&conn->c_laddr, &conn->c_faddr);
|
||||||
|
|
||||||
rds_stats_inc(s_conn_reset);
|
rds_stats_inc(s_conn_reset);
|
||||||
rds_send_reset(conn);
|
rds_send_path_reset(cp);
|
||||||
conn->c_flags = 0;
|
cp->cp_flags = 0;
|
||||||
|
|
||||||
/* Do not clear next_rx_seq here, else we cannot distinguish
|
/* Do not clear next_rx_seq here, else we cannot distinguish
|
||||||
* retransmitted packets from new packets, and will hand all
|
* 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);
|
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 */
|
/* 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
|
* Quiesce the connection mgmt handlers before we start tearing
|
||||||
* things down. We don't hold the mutex for the entire
|
* 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
|
* deadlocking with the CM handler. Instead, the CM event
|
||||||
* handler is supposed to check for state DISCONNECTING
|
* handler is supposed to check for state DISCONNECTING
|
||||||
*/
|
*/
|
||||||
mutex_lock(&conn->c_cm_lock);
|
mutex_lock(&cp->cp_cm_lock);
|
||||||
if (!rds_conn_transition(conn, RDS_CONN_UP, RDS_CONN_DISCONNECTING)
|
if (!rds_conn_path_transition(cp, RDS_CONN_UP,
|
||||||
&& !rds_conn_transition(conn, RDS_CONN_ERROR, RDS_CONN_DISCONNECTING)) {
|
RDS_CONN_DISCONNECTING) &&
|
||||||
rds_conn_error(conn, "shutdown called in state %d\n",
|
!rds_conn_path_transition(cp, RDS_CONN_ERROR,
|
||||||
atomic_read(&conn->c_state));
|
RDS_CONN_DISCONNECTING)) {
|
||||||
mutex_unlock(&conn->c_cm_lock);
|
rds_conn_path_error(cp,
|
||||||
|
"shutdown called in state %d\n",
|
||||||
|
atomic_read(&cp->cp_state));
|
||||||
|
mutex_unlock(&cp->cp_cm_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mutex_unlock(&conn->c_cm_lock);
|
mutex_unlock(&cp->cp_cm_lock);
|
||||||
|
|
||||||
wait_event(conn->c_waitq,
|
wait_event(cp->cp_waitq,
|
||||||
!test_bit(RDS_IN_XMIT, &conn->c_flags));
|
!test_bit(RDS_IN_XMIT, &cp->cp_flags));
|
||||||
wait_event(conn->c_waitq,
|
wait_event(cp->cp_waitq,
|
||||||
!test_bit(RDS_RECV_REFILL, &conn->c_flags));
|
!test_bit(RDS_RECV_REFILL, &cp->cp_flags));
|
||||||
|
|
||||||
conn->c_trans->conn_shutdown(conn);
|
if (!conn->c_trans->t_mp_capable)
|
||||||
rds_conn_reset(conn);
|
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
|
/* This can happen - eg when we're in the middle of tearing
|
||||||
* down the connection, and someone unloads the rds module.
|
* down the connection, and someone unloads the rds module.
|
||||||
* Quite reproduceable with loopback connections.
|
* Quite reproduceable with loopback connections.
|
||||||
* Mostly harmless.
|
* Mostly harmless.
|
||||||
*/
|
*/
|
||||||
rds_conn_error(conn,
|
rds_conn_path_error(cp, "%s: failed to transition "
|
||||||
"%s: failed to transition to state DOWN, "
|
"to state DOWN, current state "
|
||||||
"current state is %d\n",
|
"is %d\n", __func__,
|
||||||
__func__,
|
atomic_read(&cp->cp_state));
|
||||||
atomic_read(&conn->c_state));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,13 +352,13 @@ void rds_conn_shutdown(struct rds_connection *conn)
|
||||||
* The passive side of an IB loopback connection is never added
|
* The passive side of an IB loopback connection is never added
|
||||||
* to the conn hash, so we never trigger a reconnect on this
|
* to the conn hash, so we never trigger a reconnect on this
|
||||||
* conn - the reconnect is always triggered by the active peer. */
|
* 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();
|
rcu_read_lock();
|
||||||
if (!hlist_unhashed(&conn->c_hash_node)) {
|
if (!hlist_unhashed(&conn->c_hash_node)) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if (conn->c_trans->t_type != RDS_TRANS_TCP ||
|
if (conn->c_trans->t_type != RDS_TRANS_TCP ||
|
||||||
conn->c_path[0].cp_outgoing == 1)
|
cp->cp_outgoing == 1)
|
||||||
rds_queue_reconnect(&conn->c_path[0]);
|
rds_queue_reconnect(cp);
|
||||||
} else {
|
} else {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,6 +456,7 @@ struct rds_transport {
|
||||||
void (*conn_free)(void *data);
|
void (*conn_free)(void *data);
|
||||||
int (*conn_connect)(struct rds_connection *conn);
|
int (*conn_connect)(struct rds_connection *conn);
|
||||||
void (*conn_shutdown)(struct rds_connection *conn);
|
void (*conn_shutdown)(struct rds_connection *conn);
|
||||||
|
void (*conn_path_shutdown)(struct rds_conn_path *conn);
|
||||||
void (*xmit_prepare)(struct rds_connection *conn);
|
void (*xmit_prepare)(struct rds_connection *conn);
|
||||||
void (*xmit_path_prepare)(struct rds_conn_path *cp);
|
void (*xmit_path_prepare)(struct rds_conn_path *cp);
|
||||||
void (*xmit_complete)(struct rds_connection *conn);
|
void (*xmit_complete)(struct rds_connection *conn);
|
||||||
|
@ -653,7 +654,7 @@ struct rds_connection *rds_conn_create(struct net *net,
|
||||||
struct rds_connection *rds_conn_create_outgoing(struct net *net,
|
struct rds_connection *rds_conn_create_outgoing(struct net *net,
|
||||||
__be32 laddr, __be32 faddr,
|
__be32 laddr, __be32 faddr,
|
||||||
struct rds_transport *trans, gfp_t gfp);
|
struct rds_transport *trans, gfp_t gfp);
|
||||||
void rds_conn_shutdown(struct rds_connection *conn);
|
void rds_conn_shutdown(struct rds_conn_path *cpath);
|
||||||
void rds_conn_destroy(struct rds_connection *conn);
|
void rds_conn_destroy(struct rds_connection *conn);
|
||||||
void rds_conn_drop(struct rds_connection *conn);
|
void rds_conn_drop(struct rds_connection *conn);
|
||||||
void rds_conn_path_drop(struct rds_conn_path *cpath);
|
void rds_conn_path_drop(struct rds_conn_path *cpath);
|
||||||
|
@ -786,7 +787,7 @@ void rds_inc_info_copy(struct rds_incoming *inc,
|
||||||
|
|
||||||
/* send.c */
|
/* send.c */
|
||||||
int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len);
|
int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len);
|
||||||
void rds_send_reset(struct rds_connection *conn);
|
void rds_send_path_reset(struct rds_conn_path *conn);
|
||||||
int rds_send_xmit(struct rds_conn_path *cp);
|
int rds_send_xmit(struct rds_conn_path *cp);
|
||||||
struct sockaddr_in;
|
struct sockaddr_in;
|
||||||
void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest);
|
void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest);
|
||||||
|
|
|
@ -62,7 +62,7 @@ static void rds_send_remove_from_sock(struct list_head *messages, int status);
|
||||||
* Reset the send state. Callers must ensure that this doesn't race with
|
* Reset the send state. Callers must ensure that this doesn't race with
|
||||||
* rds_send_xmit().
|
* rds_send_xmit().
|
||||||
*/
|
*/
|
||||||
static void rds_send_path_reset(struct rds_conn_path *cp)
|
void rds_send_path_reset(struct rds_conn_path *cp)
|
||||||
{
|
{
|
||||||
struct rds_message *rm, *tmp;
|
struct rds_message *rm, *tmp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -99,12 +99,7 @@ static void rds_send_path_reset(struct rds_conn_path *cp)
|
||||||
list_splice_init(&cp->cp_retrans, &cp->cp_send_queue);
|
list_splice_init(&cp->cp_retrans, &cp->cp_send_queue);
|
||||||
spin_unlock_irqrestore(&cp->cp_lock, flags);
|
spin_unlock_irqrestore(&cp->cp_lock, flags);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rds_send_path_reset);
|
||||||
void rds_send_reset(struct rds_connection *conn)
|
|
||||||
{
|
|
||||||
rds_send_path_reset(&conn->c_path[0]);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(rds_send_reset);
|
|
||||||
|
|
||||||
static int acquire_in_xmit(struct rds_conn_path *cp)
|
static int acquire_in_xmit(struct rds_conn_path *cp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,7 +186,7 @@ void rds_tcp_reset_callbacks(struct socket *sock,
|
||||||
release_sock(osock->sk);
|
release_sock(osock->sk);
|
||||||
sock_release(osock);
|
sock_release(osock);
|
||||||
newsock:
|
newsock:
|
||||||
rds_send_reset(conn);
|
rds_send_path_reset(&conn->c_path[0]);
|
||||||
lock_sock(sock->sk);
|
lock_sock(sock->sk);
|
||||||
write_lock_bh(&sock->sk->sk_callback_lock);
|
write_lock_bh(&sock->sk->sk_callback_lock);
|
||||||
tc->t_sock = sock;
|
tc->t_sock = sock;
|
||||||
|
|
|
@ -225,7 +225,7 @@ void rds_shutdown_worker(struct work_struct *work)
|
||||||
struct rds_conn_path,
|
struct rds_conn_path,
|
||||||
cp_down_w);
|
cp_down_w);
|
||||||
|
|
||||||
rds_conn_shutdown(cp->cp_conn);
|
rds_conn_shutdown(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rds_threads_exit(void)
|
void rds_threads_exit(void)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче