xprtrdma: Micro-optimize MR DMA-unmapping
authorChuck Lever <chuck.lever@oracle.com>
Mon, 9 Nov 2020 19:40:19 +0000 (14:40 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Wed, 11 Nov 2020 15:57:39 +0000 (10:57 -0500)
Now that rpcrdma_ep is no longer part of rpcrdma_xprt, there are
four or five serial address dereferences needed to get to the
IB device needed for DMA unmapping.

Instead, let's use the same pattern that regbufs use: cache a
pointer to the device in the MR, and use that as the indication
that unmapping is necessary.

This also guarantees that the exact same device is used for DMA
mapping and unmapping, even if the r_xprt's ep has been replaced. I
don't think this can happen today, but future changes might break
this assumption.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
net/sunrpc/xprtrdma/frwr_ops.c
net/sunrpc/xprtrdma/xprt_rdma.h

index e93b3457b958b58b60799812c93cb923e27919b9..baca49fe83af2e8379fc60fe6e54a4c268778e68 100644 (file)
@@ -67,11 +67,11 @@ void frwr_release_mr(struct rpcrdma_mr *mr)
 
 static void frwr_mr_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr)
 {
-       if (mr->mr_dir != DMA_NONE) {
+       if (mr->mr_device) {
                trace_xprtrdma_mr_unmap(mr);
-               ib_dma_unmap_sg(r_xprt->rx_ep->re_id->device,
-                               mr->mr_sg, mr->mr_nents, mr->mr_dir);
-               mr->mr_dir = DMA_NONE;
+               ib_dma_unmap_sg(mr->mr_device, mr->mr_sg, mr->mr_nents,
+                               mr->mr_dir);
+               mr->mr_device = NULL;
        }
 }
 
@@ -145,7 +145,7 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr)
 
        mr->mr_xprt = r_xprt;
        mr->frwr.fr_mr = frmr;
-       mr->mr_dir = DMA_NONE;
+       mr->mr_device = NULL;
        INIT_LIST_HEAD(&mr->mr_list);
        init_completion(&mr->frwr.fr_linv_done);
 
@@ -330,6 +330,7 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
                                  mr->mr_dir);
        if (!dma_nents)
                goto out_dmamap_err;
+       mr->mr_device = ep->re_id->device;
 
        ibmr = mr->frwr.fr_mr;
        n = ib_map_mr_sg(ibmr, mr->mr_sg, dma_nents, NULL, PAGE_SIZE);
@@ -356,7 +357,6 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
        return seg;
 
 out_dmamap_err:
-       mr->mr_dir = DMA_NONE;
        trace_xprtrdma_frwr_sgerr(mr, i);
        return ERR_PTR(-EIO);
 
index 6a45bf241ec01b51c4b7819562da43c9f65d1fa8..94b28657aeeb829c52c62bcf2e1e6d34e3d0987e 100644 (file)
@@ -243,6 +243,7 @@ struct rpcrdma_req;
 struct rpcrdma_mr {
        struct list_head        mr_list;
        struct rpcrdma_req      *mr_req;
+       struct ib_device        *mr_device;
        struct scatterlist      *mr_sg;
        int                     mr_nents;
        enum dma_data_direction mr_dir;