Commit 394b2c77 authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker
Browse files

xprtrdma: Fix error handling in rpcrdma_prepare_msg_sges()



When this function fails, it needs to undo the DMA mappings it's
done so far. Otherwise these are leaked.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent ad99f053
Loading
Loading
Loading
Loading
+24 −14
Original line number Diff line number Diff line
@@ -511,6 +511,28 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
	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