]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: make sure rds_send_drop_to properly takes the m_rs_lock
authorChris Mason <chris.mason@oracle.com>
Fri, 3 Feb 2012 16:09:07 +0000 (11:09 -0500)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 23:41:33 +0000 (16:41 -0700)
rds_send_drop_to is used during socket tear down to find all the
messages on the socket and clean them up.  It can race with the
acking code unless it takes the m_rs_lock on each and every message.

This plugs a hole where we didn't take m_rs_lock on any message that
didn't have the RDS_MSG_ON_CONN set.  Taking m_rs_lock avoids
double frees and other memory corruptions as the ack code trusts
the message m_rs pointer on a socket that had actually been freed.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
Signed-off-by: Bang Nguyen <bang.nguyen@oracle.com>
net/rds/send.c

index 567f4b292a9cc321a6d3b0bdb788e37f08d8a6a8..f69d269dac2e39574c463e44e77ff3b842a9537f 100644 (file)
@@ -781,8 +781,23 @@ 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);
-
                rds_message_wait(rm);
+
+               /*
+                * just in case the code above skipped this message
+                * because RDS_MSG_ON_CONN wasn't set, run it again here
+                * taking m_rs_lock is the only thing that keeps us
+                * from racing with ack processing.
+                */
+               spin_lock_irqsave(&rm->m_rs_lock, flags);
+
+               spin_lock(&rs->rs_lock);
+               __rds_send_complete(rs, rm, RDS_RDMA_CANCELED);
+               spin_unlock(&rs->rs_lock);
+
+               rm->m_rs = NULL;
+               spin_unlock_irqrestore(&rm->m_rs_lock, flags);
+
                rds_message_put(rm);
        }
 }