aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/send.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-05-11 15:11:11 -0700
committerAndy Grover <andy.grover@oracle.com>2010-09-08 18:15:09 -0700
commit7e3f2952eeb1a0fe2aa9882fd1705a88f9d89b35 (patch)
tree903d89d0d1184bd1f33df2b5036615d1c40cfb06 /net/rds/send.c
parentrds: Use RCU for the bind lookup searches (diff)
downloadlinux-dev-7e3f2952eeb1a0fe2aa9882fd1705a88f9d89b35.tar.xz
linux-dev-7e3f2952eeb1a0fe2aa9882fd1705a88f9d89b35.zip
rds: don't let RDS shutdown a connection while senders are present
This is the first in a long line of patches that tries to fix races between RDS connection shutdown and RDS traffic. Here we are maintaining a count of active senders to make sure the connection doesn't go away while they are using it. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'net/rds/send.c')
-rw-r--r--net/rds/send.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index 8e3fd9981c2e..d35c43ff792e 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -60,15 +60,23 @@ void rds_send_reset(struct rds_connection *conn)
struct rds_message *rm, *tmp;
unsigned long flags;
+ spin_lock_irqsave(&conn->c_send_lock, flags);
if (conn->c_xmit_rm) {
+ rm = conn->c_xmit_rm;
+ conn->c_xmit_rm = NULL;
/* Tell the user the RDMA op is no longer mapped by the
* 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 */
- rds_message_unmapped(conn->c_xmit_rm);
- rds_message_put(conn->c_xmit_rm);
- conn->c_xmit_rm = NULL;
+printk(KERN_CRIT "send reset unmapping %p\n", rm);
+ rds_message_unmapped(rm);
+ spin_unlock_irqrestore(&conn->c_send_lock, flags);
+
+ rds_message_put(rm);
+ } else {
+ spin_unlock_irqrestore(&conn->c_send_lock, flags);
}
+
conn->c_xmit_sg = 0;
conn->c_xmit_hdr_off = 0;
conn->c_xmit_data_off = 0;
@@ -131,6 +139,7 @@ restart:
ret = -ENOMEM;
goto out;
}
+ atomic_inc(&conn->c_senders);
if (conn->c_trans->xmit_prepare)
conn->c_trans->xmit_prepare(conn);
@@ -350,6 +359,8 @@ restart:
rds_send_remove_from_sock(&to_be_dropped, RDS_RDMA_DROPPED);
}
+ atomic_dec(&conn->c_senders);
+
/*
* Other senders will see we have c_send_lock and exit. We
* need to recheck the send queue and race again for c_send_lock