Skip to content

Commit e814eec

Browse files
committed
svcrdma: Fix page leak in svc_rdma_recv_read_chunk()
Commit 07d0ff3 ("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: 07d0ff3 ("svcrdma: Clean up Read chunk path") Signed-off-by: Chuck Lever <[email protected]>
1 parent 10b9d99 commit e814eec

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

net/sunrpc/xprtrdma/svc_rdma_rw.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,6 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
684684
struct svc_rdma_read_info *info,
685685
__be32 *p)
686686
{
687-
unsigned int i;
688687
int ret;
689688

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

710-
/* Pages under I/O have been copied to head->rc_pages.
711-
* Prevent their premature release by svc_xprt_release() .
712-
*/
713-
for (i = 0; i < info->ri_readctxt->rc_page_count; i++)
714-
rqstp->rq_pages[i] = NULL;
715-
716709
return ret;
717710
}
718711

@@ -807,6 +800,26 @@ static int svc_rdma_build_pz_read_chunk(struct svc_rqst *rqstp,
807800
return ret;
808801
}
809802

803+
/* Pages under I/O have been copied to head->rc_pages. Ensure they
804+
* are not released by svc_xprt_release() until the I/O is complete.
805+
*
806+
* This has to be done after all Read WRs are constructed to properly
807+
* handle a page that is part of I/O on behalf of two different RDMA
808+
* segments.
809+
*
810+
* Do this only if I/O has been posted. Otherwise, we do indeed want
811+
* svc_xprt_release() to clean things up properly.
812+
*/
813+
static void svc_rdma_save_io_pages(struct svc_rqst *rqstp,
814+
const unsigned int start,
815+
const unsigned int num_pages)
816+
{
817+
unsigned int i;
818+
819+
for (i = start; i < num_pages + start; i++)
820+
rqstp->rq_pages[i] = NULL;
821+
}
822+
810823
/**
811824
* svc_rdma_recv_read_chunk - Pull a Read chunk from the client
812825
* @rdma: controlling RDMA transport
@@ -860,6 +873,7 @@ int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp,
860873
ret = svc_rdma_post_chunk_ctxt(&info->ri_cc);
861874
if (ret < 0)
862875
goto out_err;
876+
svc_rdma_save_io_pages(rqstp, 0, head->rc_page_count);
863877
return 0;
864878

865879
out_err:

0 commit comments

Comments
 (0)