aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2008-08-13 12:05:41 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-08-13 16:57:31 -0400
commit24b8b44780a2c53ecb738f4a1c08d114f5eda27c (patch)
treef772e59438783c6230158ea65bd5aeb3f84f4202 /net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
parent30a2f3c60a84092c8084dfe788b710f8d0768cd4 (diff)
svcrdma: Fix race between svc_rdma_recvfrom thread and the dto_tasklet
RDMA_READ completions are kept on a separate queue from the general I/O request queue. Since a separate lock is used to protect the RDMA_READ completion queue, a race exists between the dto_tasklet and the svc_rdma_recvfrom thread where the dto_tasklet sets the XPT_DATA bit and adds I/O to the read-completion queue. Concurrently, the recvfrom thread checks the generic queue, finds it empty and resets the XPT_DATA bit. A subsequent svc_xprt_enqueue will fail to enqueue the transport for I/O and cause the transport to "stall". The fix is to protect both lists with the same lock and set the XPT_DATA bit with this lock held. Signed-off-by: Tom Tucker <tom@opengridcomputing.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net/sunrpc/xprtrdma/svc_rdma_recvfrom.c')
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index b4b17f44cb29..74de31a06616 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -443,18 +443,18 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
443 443
444 dprintk("svcrdma: rqstp=%p\n", rqstp); 444 dprintk("svcrdma: rqstp=%p\n", rqstp);
445 445
446 spin_lock_bh(&rdma_xprt->sc_read_complete_lock); 446 spin_lock_bh(&rdma_xprt->sc_rq_dto_lock);
447 if (!list_empty(&rdma_xprt->sc_read_complete_q)) { 447 if (!list_empty(&rdma_xprt->sc_read_complete_q)) {
448 ctxt = list_entry(rdma_xprt->sc_read_complete_q.next, 448 ctxt = list_entry(rdma_xprt->sc_read_complete_q.next,
449 struct svc_rdma_op_ctxt, 449 struct svc_rdma_op_ctxt,
450 dto_q); 450 dto_q);
451 list_del_init(&ctxt->dto_q); 451 list_del_init(&ctxt->dto_q);
452 } 452 }
453 spin_unlock_bh(&rdma_xprt->sc_read_complete_lock); 453 if (ctxt) {
454 if (ctxt) 454 spin_unlock_bh(&rdma_xprt->sc_rq_dto_lock);
455 return rdma_read_complete(rqstp, ctxt); 455 return rdma_read_complete(rqstp, ctxt);
456 }
456 457
457 spin_lock_bh(&rdma_xprt->sc_rq_dto_lock);
458 if (!list_empty(&rdma_xprt->sc_rq_dto_q)) { 458 if (!list_empty(&rdma_xprt->sc_rq_dto_q)) {
459 ctxt = list_entry(rdma_xprt->sc_rq_dto_q.next, 459 ctxt = list_entry(rdma_xprt->sc_rq_dto_q.next,
460 struct svc_rdma_op_ctxt, 460 struct svc_rdma_op_ctxt,