Skip to content

Commit

Permalink
xprtrdma: Fix DMA scatter-gather list mapping imbalance
Browse files Browse the repository at this point in the history
The @nents value that was passed to ib_dma_map_sg() has to be passed
to the matching ib_dma_unmap_sg() call. If ib_dma_map_sg() choses to
concatenate sg entries, it will return a different nents value than
it was passed.

The bug was exposed by recent changes to the AMD IOMMU driver, which
enabled sg entry concatenation.

Looking all the way back to commit 4143f34 ("xprtrdma: Port to
new memory registration API") and reviewing other kernel ULPs, it's
not clear that the frwr_map() logic was ever correct for this case.

Reported-by: Andre Tomt <[email protected]>
Suggested-by: Robin Murphy <[email protected]>
Signed-off-by: Chuck Lever <[email protected]>
Cc: [email protected]
Reviewed-by: Jason Gunthorpe <[email protected]>
Signed-off-by: Anna Schumaker <[email protected]>
  • Loading branch information
chucklever authored and amschuma-ntap committed Feb 13, 2020
1 parent efeda80 commit ca1c671
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions net/sunrpc/xprtrdma/frwr_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
{
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
struct ib_reg_wr *reg_wr;
int i, n, dma_nents;
struct ib_mr *ibmr;
int i, n;
u8 key;

if (nsegs > ia->ri_max_frwr_depth)
Expand All @@ -313,15 +313,16 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
break;
}
mr->mr_dir = rpcrdma_data_dir(writing);
mr->mr_nents = i;

mr->mr_nents =
ib_dma_map_sg(ia->ri_id->device, mr->mr_sg, i, mr->mr_dir);
if (!mr->mr_nents)
dma_nents = ib_dma_map_sg(ia->ri_id->device, mr->mr_sg, mr->mr_nents,
mr->mr_dir);
if (!dma_nents)
goto out_dmamap_err;

ibmr = mr->frwr.fr_mr;
n = ib_map_mr_sg(ibmr, mr->mr_sg, mr->mr_nents, NULL, PAGE_SIZE);
if (unlikely(n != mr->mr_nents))
n = ib_map_mr_sg(ibmr, mr->mr_sg, dma_nents, NULL, PAGE_SIZE);
if (n != dma_nents)
goto out_mapmr_err;

ibmr->iova &= 0x00000000ffffffff;
Expand Down

0 comments on commit ca1c671

Please sign in to comment.