Commit e814eecb authored by Chuck Lever's avatar Chuck Lever
Browse files

svcrdma: Fix page leak in svc_rdma_recv_read_chunk()



Commit 07d0ff3b ("svcrdma: Clean up Read chunk path") moved the
page saver logic so that it gets executed event when an error occurs.
In that case, the I/O is never posted, and those pages are then
leaked. Errors in this path, however, are quite rare.

Fixes: 07d0ff3b ("svcrdma: Clean up Read chunk path")
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 10b9d99a
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -684,7 +684,6 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
				     struct svc_rdma_read_info *info,
				     __be32 *p)
{
	unsigned int i;
	int ret;

	ret = -EINVAL;
@@ -707,12 +706,6 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
		info->ri_chunklen += rs_length;
	}

	/* Pages under I/O have been copied to head->rc_pages.
	 * Prevent their premature release by svc_xprt_release() .
	 */
	for (i = 0; i < info->ri_readctxt->rc_page_count; i++)
		rqstp->rq_pages[i] = NULL;

	return ret;
}

@@ -807,6 +800,26 @@ out:
	return ret;
}

/* Pages under I/O have been copied to head->rc_pages. Ensure they
 * are not released by svc_xprt_release() until the I/O is complete.
 *
 * This has to be done after all Read WRs are constructed to properly
 * handle a page that is part of I/O on behalf of two different RDMA
 * segments.
 *
 * Do this only if I/O has been posted. Otherwise, we do indeed want
 * svc_xprt_release() to clean things up properly.
 */
static void svc_rdma_save_io_pages(struct svc_rqst *rqstp,
				   const unsigned int start,
				   const unsigned int num_pages)
{
	unsigned int i;

	for (i = start; i < num_pages + start; i++)
		rqstp->rq_pages[i] = NULL;
}

/**
 * svc_rdma_recv_read_chunk - Pull a Read chunk from the client
 * @rdma: controlling RDMA transport
@@ -860,6 +873,7 @@ int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp,
	ret = svc_rdma_post_chunk_ctxt(&info->ri_cc);
	if (ret < 0)
		goto out_err;
	svc_rdma_save_io_pages(rqstp, 0, head->rc_page_count);
	return 0;

out_err: