Skip to content

Commit

Permalink
rds: Fix RDMA message reference counting
Browse files Browse the repository at this point in the history
The RDS send_xmit code was trying to get fancy with message
counting and was dropping the final reference on the RDMA messages
too early.  This resulted in memory corruption and oopsen.

The fix here is to always add a ref as the parts of the message passes
through rds_send_xmit, and always drop a ref as the parts of the message
go through completion handling.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason authored and Andy Grover committed Sep 9, 2010
1 parent 7e3f295 commit c9e6538
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 8 deletions.
11 changes: 6 additions & 5 deletions net/rds/ib_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,12 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context)
if (send->s_queued + HZ/2 < jiffies)
rds_ib_stats_inc(s_ib_tx_stalled);

if (&send->s_op == &rm->m_final_op) {
/* If anyone waited for this message to get flushed out, wake
* them up now */
rds_message_unmapped(rm);

if (send->s_op) {
if (send->s_op == rm->m_final_op) {
/* If anyone waited for this message to get flushed out, wake
* them up now */
rds_message_unmapped(rm);
}
rds_message_put(rm);
send->s_op = NULL;
}
Expand Down
11 changes: 8 additions & 3 deletions net/rds/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ void rds_send_reset(struct rds_connection *conn)
* transport. This isn't entirely true (it's flushed out
* independently) but as the connection is down, there's
* no ongoing RDMA to/from that memory */
printk(KERN_CRIT "send reset unmapping %p\n", rm);
rds_message_unmapped(rm);
spin_unlock_irqrestore(&conn->c_send_lock, flags);

Expand Down Expand Up @@ -234,10 +233,13 @@ int rds_send_xmit(struct rds_connection *conn)

/* The transport either sends the whole rdma or none of it */
if (rm->rdma.op_active && !conn->c_xmit_rdma_sent) {
rds_message_addref(rm);
rm->m_final_op = &rm->rdma;
ret = conn->c_trans->xmit_rdma(conn, &rm->rdma);
if (ret)
if (ret) {
rds_message_put(rm);
break;
}
conn->c_xmit_rdma_sent = 1;

/* The transport owns the mapped memory for now.
Expand All @@ -246,10 +248,13 @@ int rds_send_xmit(struct rds_connection *conn)
}

if (rm->atomic.op_active && !conn->c_xmit_atomic_sent) {
rds_message_addref(rm);
rm->m_final_op = &rm->atomic;
ret = conn->c_trans->xmit_atomic(conn, &rm->atomic);
if (ret)
if (ret) {
rds_message_put(rm);
break;
}
conn->c_xmit_atomic_sent = 1;

/* The transport owns the mapped memory for now.
Expand Down

0 comments on commit c9e6538

Please sign in to comment.