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: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
Chuck Lever 2017-10-20 10:47:47 -04:00 коммит произвёл Anna Schumaker
Родитель ad99f05307
Коммит 394b2c77cb
1 изменённых файлов: 24 добавлений и 14 удалений

Просмотреть файл

@ -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