aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtrdma
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2008-05-06 11:04:50 -0400
committerTom Tucker <tom@opengridcomputing.com>2008-05-19 08:33:49 -0400
commitd16d40093a95f2b31007d7a7abefc50e6b27e236 (patch)
tree9237f839221763fccb50c6115e9caf9584311539 /net/sunrpc/xprtrdma
parent58e8f62137f1c55fe3d31234167660f2ce509297 (diff)
svcrdma: Return error from rdma_read_xdr so caller knows to free context
The rdma_read_xdr function did not discriminate between no read-list and an error posting the read-list. This results in a leak of a page if there is an error posting the read-list. Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
Diffstat (limited to 'net/sunrpc/xprtrdma')
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index f3a108a864ad..5e03d95b25e2 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -260,11 +260,16 @@ static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count)
260 * On our side, we need to read into a pagelist. The first page immediately 260 * On our side, we need to read into a pagelist. The first page immediately
261 * follows the RPC header. 261 * follows the RPC header.
262 * 262 *
263 * This function returns 1 to indicate success. The data is not yet in 263 * This function returns:
264 * 0 - No error and no read-list found.
265 *
266 * 1 - Successful read-list processing. The data is not yet in
264 * the pagelist and therefore the RPC request must be deferred. The 267 * the pagelist and therefore the RPC request must be deferred. The
265 * I/O completion will enqueue the transport again and 268 * I/O completion will enqueue the transport again and
266 * svc_rdma_recvfrom will complete the request. 269 * svc_rdma_recvfrom will complete the request.
267 * 270 *
271 * <0 - Error processing/posting read-list.
272 *
268 * NOTE: The ctxt must not be touched after the last WR has been posted 273 * NOTE: The ctxt must not be touched after the last WR has been posted
269 * because the I/O completion processing may occur on another 274 * because the I/O completion processing may occur on another
270 * processor and free / modify the context. Ne touche pas! 275 * processor and free / modify the context. Ne touche pas!
@@ -398,7 +403,7 @@ next_sge:
398 svc_rdma_put_context(head, 1); 403 svc_rdma_put_context(head, 1);
399 head = ctxt; 404 head = ctxt;
400 } 405 }
401 return 0; 406 return err;
402 } 407 }
403 408
404 return 1; 409 return 1;
@@ -532,14 +537,18 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
532 goto close_out; 537 goto close_out;
533 } 538 }
534 539
535 /* Read read-list data. If we would need to wait, defer 540 /* Read read-list data. */
536 * it. Not that in this case, we don't return the RQ credit 541 ret = rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt);
537 * until after the read completes. 542 if (ret > 0) {
538 */ 543 /* read-list posted, defer until data received from client. */
539 if (rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt)) {
540 svc_xprt_received(xprt); 544 svc_xprt_received(xprt);
541 return 0; 545 return 0;
542 } 546 }
547 if (ret < 0) {
548 /* Post of read-list failed, free context. */
549 svc_rdma_put_context(ctxt, 1);
550 return 0;
551 }
543 552
544 ret = rqstp->rq_arg.head[0].iov_len 553 ret = rqstp->rq_arg.head[0].iov_len
545 + rqstp->rq_arg.page_len 554 + rqstp->rq_arg.page_len