aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/send.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-05-11 18:14:16 -0400
committerAndy Grover <andy.grover@oracle.com>2010-09-08 21:15:10 -0400
commitc9e65383a20d9a656db70efbf67e57f8115ad776 (patch)
tree3055f38ada5a60e858fe66e12353cad37e8ebdd5 /net/rds/send.c
parent7e3f2952eeb1a0fe2aa9882fd1705a88f9d89b35 (diff)
rds: Fix RDMA message reference counting
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>
Diffstat (limited to 'net/rds/send.c')
-rw-r--r--net/rds/send.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index d35c43ff792e..5c6d4a0be0d7 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -68,7 +68,6 @@ void rds_send_reset(struct rds_connection *conn)
68 * transport. This isn't entirely true (it's flushed out 68 * transport. This isn't entirely true (it's flushed out
69 * independently) but as the connection is down, there's 69 * independently) but as the connection is down, there's
70 * no ongoing RDMA to/from that memory */ 70 * no ongoing RDMA to/from that memory */
71printk(KERN_CRIT "send reset unmapping %p\n", rm);
72 rds_message_unmapped(rm); 71 rds_message_unmapped(rm);
73 spin_unlock_irqrestore(&conn->c_send_lock, flags); 72 spin_unlock_irqrestore(&conn->c_send_lock, flags);
74 73
@@ -234,10 +233,13 @@ restart:
234 233
235 /* The transport either sends the whole rdma or none of it */ 234 /* The transport either sends the whole rdma or none of it */
236 if (rm->rdma.op_active && !conn->c_xmit_rdma_sent) { 235 if (rm->rdma.op_active && !conn->c_xmit_rdma_sent) {
236 rds_message_addref(rm);
237 rm->m_final_op = &rm->rdma; 237 rm->m_final_op = &rm->rdma;
238 ret = conn->c_trans->xmit_rdma(conn, &rm->rdma); 238 ret = conn->c_trans->xmit_rdma(conn, &rm->rdma);
239 if (ret) 239 if (ret) {
240 rds_message_put(rm);
240 break; 241 break;
242 }
241 conn->c_xmit_rdma_sent = 1; 243 conn->c_xmit_rdma_sent = 1;
242 244
243 /* The transport owns the mapped memory for now. 245 /* The transport owns the mapped memory for now.
@@ -246,10 +248,13 @@ restart:
246 } 248 }
247 249
248 if (rm->atomic.op_active && !conn->c_xmit_atomic_sent) { 250 if (rm->atomic.op_active && !conn->c_xmit_atomic_sent) {
251 rds_message_addref(rm);
249 rm->m_final_op = &rm->atomic; 252 rm->m_final_op = &rm->atomic;
250 ret = conn->c_trans->xmit_atomic(conn, &rm->atomic); 253 ret = conn->c_trans->xmit_atomic(conn, &rm->atomic);
251 if (ret) 254 if (ret) {
255 rds_message_put(rm);
252 break; 256 break;
257 }
253 conn->c_xmit_atomic_sent = 1; 258 conn->c_xmit_atomic_sent = 1;
254 259
255 /* The transport owns the mapped memory for now. 260 /* The transport owns the mapped memory for now.