RDS: rds_send_xmit() locking/irq fixes

rds_message_put() cannot be called with irqs off, so move it after
irqs are re-enabled.

Spinlocks throughout the function do not to use _irqsave because
the lock of c_send_lock at top already disabled irqs.

Signed-off-by: Andy Grover <andy.grover@oracle.com>
This commit is contained in:
Andy Grover 2010-03-23 17:48:04 -07:00
parent 049ee3f500
commit 2ad8099b58

View file

@ -168,7 +168,7 @@ int rds_send_xmit(struct rds_connection *conn)
if (!rm) { if (!rm) {
unsigned int len; unsigned int len;
spin_lock_irqsave(&conn->c_lock, flags); spin_lock(&conn->c_lock);
if (!list_empty(&conn->c_send_queue)) { if (!list_empty(&conn->c_send_queue)) {
rm = list_entry(conn->c_send_queue.next, rm = list_entry(conn->c_send_queue.next,
@ -183,7 +183,7 @@ int rds_send_xmit(struct rds_connection *conn)
list_move_tail(&rm->m_conn_item, &conn->c_retrans); list_move_tail(&rm->m_conn_item, &conn->c_retrans);
} }
spin_unlock_irqrestore(&conn->c_lock, flags); spin_unlock(&conn->c_lock);
if (!rm) { if (!rm) {
was_empty = 1; was_empty = 1;
@ -199,11 +199,10 @@ int rds_send_xmit(struct rds_connection *conn)
*/ */
if (rm->rdma.op_active && if (rm->rdma.op_active &&
test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags)) { test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags)) {
spin_lock_irqsave(&conn->c_lock, flags); spin_lock(&conn->c_lock);
if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags)) if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags))
list_move(&rm->m_conn_item, &to_be_dropped); list_move(&rm->m_conn_item, &to_be_dropped);
spin_unlock_irqrestore(&conn->c_lock, flags); spin_unlock(&conn->c_lock);
rds_message_put(rm);
continue; continue;
} }
@ -326,10 +325,6 @@ int rds_send_xmit(struct rds_connection *conn)
} }
} }
/* Nuke any messages we decided not to retransmit. */
if (!list_empty(&to_be_dropped))
rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_DROPPED);
if (conn->c_trans->xmit_complete) if (conn->c_trans->xmit_complete)
conn->c_trans->xmit_complete(conn); conn->c_trans->xmit_complete(conn);
@ -347,6 +342,14 @@ int rds_send_xmit(struct rds_connection *conn)
*/ */
spin_unlock_irqrestore(&conn->c_send_lock, flags); spin_unlock_irqrestore(&conn->c_send_lock, flags);
/* Nuke any messages we decided not to retransmit. */
if (!list_empty(&to_be_dropped)) {
/* irqs on here, so we can put(), unlike above */
list_for_each_entry(rm, &to_be_dropped, m_conn_item)
rds_message_put(rm);
rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_DROPPED);
}
if (send_quota == 0 && !was_empty) { if (send_quota == 0 && !was_empty) {
/* We exhausted the send quota, but there's work left to /* We exhausted the send quota, but there's work left to
* do. Return and (re-)schedule the send worker. * do. Return and (re-)schedule the send worker.