From: Chuck Lever <chuck.lever@oracle.com>
Date: Fri, 20 Oct 2017 10:47:47 -0400
Subject: xprtrdma: Fix error handling in rpcrdma_prepare_msg_sges()
Patch-mainline: v4.15-rc1
Git-commit: 394b2c77cb761fb1382b0e97b7cdff2dd717b5ee
References: bsc#1103992 FATE#326009
When this function fails, it needs to undo the DMA mappings it's
done so far. Otherwise these are leaked.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
net/sunrpc/xprtrdma/rpc_rdma.c | 38 ++++++++++++++++++++++++--------------
1 file changed, 24 insertions(+), 14 deletions(-)
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -511,6 +511,28 @@ rpcrdma_encode_reply_chunk(struct rpcrdm
return 0;
}
+/**
+ * rpcrdma_unmap_sges - DMA-unmap Send buffers
+ * @ia: interface adapter (device)
+ * @req: req with possibly some SGEs to be DMA unmapped
+ *
+ */
+void
+rpcrdma_unmap_sges(struct rpcrdma_ia *ia, struct rpcrdma_req *req)
+{
+ struct ib_sge *sge;
+ unsigned int count;
+
+ /* The first two SGEs contain the transport header and
+ * the inline buffer. These are always left mapped so
+ * they can be cheaply re-used.
+ */
+ sge = &req->rl_send_sge[2];
+ for (count = req->rl_mapped_sges; count--; sge++)
+ ib_dma_unmap_page(ia->ri_device,
+ sge->addr, sge->length, DMA_TO_DEVICE);
+}
+
/* Prepare the RPC-over-RDMA header SGE.
*/
static bool
@@ -641,10 +663,12 @@ out:
return true;
out_mapping_overflow:
+ rpcrdma_unmap_sges(ia, req);
pr_err("rpcrdma: too many Send SGEs (%u)\n", sge_no);
return false;
out_mapping_err:
+ rpcrdma_unmap_sges(ia, req);
pr_err("rpcrdma: Send mapping error\n");
return false;
}
@@ -671,20 +695,6 @@ out_map:
return false;
}
-void
-rpcrdma_unmap_sges(struct rpcrdma_ia *ia, struct rpcrdma_req *req)
-{
- struct ib_device *device = ia->ri_device;
- struct ib_sge *sge;
- int count;
-
- sge = &req->rl_send_sge[2];
- for (count = req->rl_mapped_sges; count--; sge++)
- ib_dma_unmap_page(device, sge->addr, sge->length,
- DMA_TO_DEVICE);
- req->rl_mapped_sges = 0;
-}
-
/**
* rpcrdma_marshal_req - Marshal and send one RPC request
* @r_xprt: controlling transport