diff options
author | Tom Tucker <tom@opengridcomputing.com> | 2008-05-06 11:04:50 -0400 |
---|---|---|
committer | Tom Tucker <tom@opengridcomputing.com> | 2008-05-19 08:33:49 -0400 |
commit | d16d40093a95f2b31007d7a7abefc50e6b27e236 (patch) | |
tree | 9237f839221763fccb50c6115e9caf9584311539 | |
parent | 58e8f62137f1c55fe3d31234167660f2ce509297 (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>
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 23 |
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 |