Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

xprtrdma: Don't leak freed MRs



Defensive clean up. Don't set frwr->fr_mr until we know that the
scatterlist allocation has succeeded.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent af65ed40
Loading
Loading
Loading
Loading
+15 −12
Original line number Diff line number Diff line
@@ -155,36 +155,39 @@ frwr_mr_recycle_worker(struct work_struct *work)
int frwr_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mr *mr)
{
	unsigned int depth = ia->ri_max_frwr_depth;
	struct rpcrdma_frwr *frwr = &mr->frwr;
	struct scatterlist *sg;
	struct ib_mr *frmr;
	int rc;

	frwr->fr_mr = ib_alloc_mr(ia->ri_pd, ia->ri_mrtype, depth);
	if (IS_ERR(frwr->fr_mr))
	frmr = ib_alloc_mr(ia->ri_pd, ia->ri_mrtype, depth);
	if (IS_ERR(frmr))
		goto out_mr_err;

	mr->mr_sg = kcalloc(depth, sizeof(*mr->mr_sg), GFP_KERNEL);
	if (!mr->mr_sg)
	sg = kcalloc(depth, sizeof(*sg), GFP_KERNEL);
	if (!sg)
		goto out_list_err;

	frwr->fr_state = FRWR_IS_INVALID;
	mr->frwr.fr_mr = frmr;
	mr->frwr.fr_state = FRWR_IS_INVALID;
	mr->mr_dir = DMA_NONE;
	INIT_LIST_HEAD(&mr->mr_list);
	INIT_WORK(&mr->mr_recycle, frwr_mr_recycle_worker);
	sg_init_table(mr->mr_sg, depth);
	init_completion(&frwr->fr_linv_done);
	init_completion(&mr->frwr.fr_linv_done);

	sg_init_table(sg, depth);
	mr->mr_sg = sg;
	return 0;

out_mr_err:
	rc = PTR_ERR(frwr->fr_mr);
	rc = PTR_ERR(frmr);
	trace_xprtrdma_frwr_alloc(mr, rc);
	return rc;

out_list_err:
	rc = -ENOMEM;
	dprintk("RPC:       %s: sg allocation failure\n",
		__func__);
	ib_dereg_mr(frwr->fr_mr);
	return rc;
	ib_dereg_mr(frmr);
	return -ENOMEM;
}

/**