Skip to content

Commit ca1c671

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Fix DMA scatter-gather list mapping imbalance
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]>
1 parent efeda80 commit ca1c671

File tree

1 file changed

+7
-6
lines changed

1 file changed

+7
-6
lines changed

net/sunrpc/xprtrdma/frwr_ops.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
288288
{
289289
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
290290
struct ib_reg_wr *reg_wr;
291+
int i, n, dma_nents;
291292
struct ib_mr *ibmr;
292-
int i, n;
293293
u8 key;
294294

295295
if (nsegs > ia->ri_max_frwr_depth)
@@ -313,15 +313,16 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
313313
break;
314314
}
315315
mr->mr_dir = rpcrdma_data_dir(writing);
316+
mr->mr_nents = i;
316317

317-
mr->mr_nents =
318-
ib_dma_map_sg(ia->ri_id->device, mr->mr_sg, i, mr->mr_dir);
319-
if (!mr->mr_nents)
318+
dma_nents = ib_dma_map_sg(ia->ri_id->device, mr->mr_sg, mr->mr_nents,
319+
mr->mr_dir);
320+
if (!dma_nents)
320321
goto out_dmamap_err;
321322

322323
ibmr = mr->frwr.fr_mr;
323-
n = ib_map_mr_sg(ibmr, mr->mr_sg, mr->mr_nents, NULL, PAGE_SIZE);
324-
if (unlikely(n != mr->mr_nents))
324+
n = ib_map_mr_sg(ibmr, mr->mr_sg, dma_nents, NULL, PAGE_SIZE);
325+
if (n != dma_nents)
325326
goto out_mapmr_err;
326327

327328
ibmr->iova &= 0x00000000ffffffff;

0 commit comments

Comments
 (0)