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 flush them . 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. We must take m_rs_lock to access m_rs. Because of lock nesting and rs access, we also need to acquire rs_lock. Reviewed-by: Ajaykumar Hotchandani <ajaykumar.hotchandani@oracle.com> Signed-off-by: Santosh Shilimkar <ssantosh@kernel.org> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1c3be624f4
commit
dfcec251d2
1 changed files with 15 additions and 1 deletions
|
@ -778,8 +778,22 @@ 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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue