aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2016-06-29 13:52:12 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-07-11 15:50:43 -0400
commit38f1932e60ba249660bbae585f61ef2dee3313a4 (patch)
treeae8f93876ca8739cb676b13bf8d45afc468b78fb
parent92d21ac74a9e3c09b0b01c764e530657e4c85c49 (diff)
xprtrdma: Remove FMRs from the unmap list after unmapping
ib_unmap_fmr() takes a list of FMRs to unmap. However, it does not remove the FMRs from this list as it processes them. Other ib_unmap_fmr() call sites are careful to remove FMRs from the list after ib_unmap_fmr() returns. Since commit 7c7a5390dc6c8 ("xprtrdma: Add ro_unmap_sync method for FMR") fmr_op_unmap_sync passes more than one FMR to ib_unmap_fmr(), but it didn't bother to remove the FMRs from that list once the call was complete. I've noticed some instability that could be related to list tangling by the new fmr_op_unmap_sync() logic. In an abundance of caution, add some defensive logic to clean up properly after ib_unmap_fmr(). Fixes: 7c7a5390dc6c8 ("xprtrdma: Add ro_unmap_sync method for FMR") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--net/sunrpc/xprtrdma/fmr_ops.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/net/sunrpc/xprtrdma/fmr_ops.c b/net/sunrpc/xprtrdma/fmr_ops.c
index 6326ebe8b595..c748ff6f6877 100644
--- a/net/sunrpc/xprtrdma/fmr_ops.c
+++ b/net/sunrpc/xprtrdma/fmr_ops.c
@@ -63,9 +63,12 @@ static int
63__fmr_unmap(struct rpcrdma_mw *mw) 63__fmr_unmap(struct rpcrdma_mw *mw)
64{ 64{
65 LIST_HEAD(l); 65 LIST_HEAD(l);
66 int rc;
66 67
67 list_add(&mw->fmr.fmr->list, &l); 68 list_add(&mw->fmr.fmr->list, &l);
68 return ib_unmap_fmr(&l); 69 rc = ib_unmap_fmr(&l);
70 list_del_init(&mw->fmr.fmr->list);
71 return rc;
69} 72}
70 73
71/* Deferred reset of a single FMR. Generate a fresh rkey by 74/* Deferred reset of a single FMR. Generate a fresh rkey by
@@ -267,7 +270,7 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
267 seg = &req->rl_segments[i]; 270 seg = &req->rl_segments[i];
268 mw = seg->rl_mw; 271 mw = seg->rl_mw;
269 272
270 list_add(&mw->fmr.fmr->list, &unmap_list); 273 list_add_tail(&mw->fmr.fmr->list, &unmap_list);
271 274
272 i += seg->mr_nsegs; 275 i += seg->mr_nsegs;
273 } 276 }
@@ -280,7 +283,9 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
280 */ 283 */
281 for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) { 284 for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
282 seg = &req->rl_segments[i]; 285 seg = &req->rl_segments[i];
286 mw = seg->rl_mw;
283 287
288 list_del_init(&mw->fmr.fmr->list);
284 __fmr_dma_unmap(r_xprt, seg); 289 __fmr_dma_unmap(r_xprt, seg);
285 rpcrdma_put_mw(r_xprt, seg->rl_mw); 290 rpcrdma_put_mw(r_xprt, seg->rl_mw);
286 291