From: Avinash Repaka Date: Wed, 7 Sep 2016 00:54:02 +0000 (-0700) Subject: RDS: Drop the connection as part of cancel to avoid hangs X-Git-Tag: v4.1.12-92~67^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=052f6209936c0502a55f7eeaf14d21cf2bc0010c;p=users%2Fjedix%2Flinux-maple.git RDS: Drop the connection as part of cancel to avoid hangs To avoid waiting indefinitely in rds_send_drop_to(), drop the connection proactively if one of the cancelled messages is mapped. Orabug: 22506032 Signed-off-by: Avinash Repaka Signed-off-by: Santosh Shilimkar --- diff --git a/net/rds/connection.c b/net/rds/connection.c index 0d509765e383..e021746e46d0 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c @@ -655,6 +655,7 @@ static char *conn_drop_reasons[] = { [DR_CONN_CONNECT_FAIL] = "conn_connect failure", [DR_HB_TIMEOUT] = "hb timeout", [DR_RECONNECT_TIMEOUT] = "reconnect timeout", + [DR_SOCK_CANCEL] = "cancel operation on socket", [DR_IB_CONN_DROP_RACE] = "race between ESTABLISHED event and drop", [DR_IB_NOT_CONNECTING_STATE] = "conn is not in CONNECTING state", [DR_IB_QP_EVENT] = "qp event", diff --git a/net/rds/rds.h b/net/rds/rds.h index 8db391d1c567..26b80b316b2a 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -154,6 +154,7 @@ enum rds_conn_drop_src { DR_CONN_CONNECT_FAIL, DR_HB_TIMEOUT, DR_RECONNECT_TIMEOUT, + DR_SOCK_CANCEL, /* ib_cm */ DR_IB_CONN_DROP_RACE, diff --git a/net/rds/send.c b/net/rds/send.c index 3741ebdbb109..b1bc9ed75ba8 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -868,6 +868,7 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) struct rds_connection *conn; unsigned long flags; LIST_HEAD(list); + int conn_dropped = 0; /* get all the messages we're dropping under the rs lock */ spin_lock_irqsave(&rs->rs_lock, flags); @@ -929,6 +930,17 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) while (!list_empty(&list)) { rm = list_entry(list.next, struct rds_message, m_sock_item); list_del_init(&rm->m_sock_item); + + /* Drop the connection only if this is part of cancel. + * For a paticular dest and for a sock, all the rms cancelled + * belong to the same connection. + */ + if (!conn_dropped && dest && + test_bit(RDS_MSG_MAPPED, &rm->m_flags)) { + conn->c_drop_source = DR_SOCK_CANCEL; + rds_conn_drop(conn); + conn_dropped = 1; + } rds_message_wait(rm); /*