Commit 38f1932e authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker

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 7c7a5390 ("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

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

Fixes: 7c7a5390 ("xprtrdma: Add ro_unmap_sync method for FMR")
Signed-off-by: default avatarChuck Lever <>
Tested-by: default avatarSteve Wise <>
Signed-off-by: default avatarAnna Schumaker <>
parent 92d21ac7
......@@ -63,9 +63,12 @@ static int
__fmr_unmap(struct rpcrdma_mw *mw)
int rc;
list_add(&mw->fmr.fmr->list, &l);
return ib_unmap_fmr(&l);
rc = ib_unmap_fmr(&l);
return rc;
/* 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)
seg = &req->rl_segments[i];
mw = seg->rl_mw;
list_add(&mw->fmr.fmr->list, &unmap_list);
list_add_tail(&mw->fmr.fmr->list, &unmap_list);
i += seg->mr_nsegs;
......@@ -280,7 +283,9 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
seg = &req->rl_segments[i];
mw = seg->rl_mw;
__fmr_dma_unmap(r_xprt, seg);
rpcrdma_put_mw(r_xprt, seg->rl_mw);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment