]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: Drop the connection as part of cancel to avoid hangs
authorAvinash Repaka <avinash.repaka@oracle.com>
Wed, 7 Sep 2016 00:54:02 +0000 (17:54 -0700)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Thu, 13 Oct 2016 16:21:17 +0000 (09:21 -0700)
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 <avinash.repaka@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
net/rds/connection.c
net/rds/rds.h
net/rds/send.c

index 0d509765e383932a115da19010adfb4643c145fd..e021746e46d0c891f69987354ed54d04bb70ceb7 100644 (file)
@@ -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",
index 8db391d1c567a69aab05e2af44a8db5b95e0ac2b..26b80b316b2ac71005b971f943a55095c6986183 100644 (file)
@@ -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,
index 3741ebdbb10930e6e457bdf2f05819a46e894b4e..b1bc9ed75ba8fa1432b65a91d3e207a8729b4034 100644 (file)
@@ -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);
 
                /*