From: Chris Mason Date: Fri, 3 Feb 2012 16:09:07 +0000 (-0500) Subject: RDS: make sure rds_send_drop_to properly takes the m_rs_lock X-Git-Tag: v4.1.12-92~319^2^2~2^2~35 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=fcd07c90227362109190d2815106d61bae0fbdc2;p=users%2Fjedix%2Flinux-maple.git RDS: make sure rds_send_drop_to properly takes the m_rs_lock 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 Signed-off-by: Bang Nguyen --- diff --git a/net/rds/send.c b/net/rds/send.c index 567f4b292a9c..f69d269dac2e 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -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); } }