svcrdma: Fix page leak in svc_rdma_recv_read_chunk()
Commit07d0ff3b0c
("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:07d0ff3b0c
("svcrdma: Clean up Read chunk path") Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
10b9d99a3d
commit
e814eecbe3
|
@ -684,7 +684,6 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
|
||||||
struct svc_rdma_read_info *info,
|
struct svc_rdma_read_info *info,
|
||||||
__be32 *p)
|
__be32 *p)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -707,12 +706,6 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
|
||||||
info->ri_chunklen += rs_length;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,6 +800,26 @@ out:
|
||||||
return ret;
|
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
|
* svc_rdma_recv_read_chunk - Pull a Read chunk from the client
|
||||||
* @rdma: controlling RDMA transport
|
* @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);
|
ret = svc_rdma_post_chunk_ctxt(&info->ri_cc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
svc_rdma_save_io_pages(rqstp, 0, head->rc_page_count);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
|
|
Loading…
Reference in New Issue