svcrdma: Return error from rdma_read_xdr so caller knows to free context
authorTom Tucker <tom@opengridcomputing.com>
Tue, 6 May 2008 15:04:50 +0000 (10:04 -0500)
committerTom Tucker <tom@opengridcomputing.com>
Mon, 19 May 2008 12:33:49 +0000 (07:33 -0500)
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>
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

index f3a108a..5e03d95 100644 (file)
@@ -260,11 +260,16 @@ static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count)
  * On our side, we need to read into a pagelist. The first page immediately
  * follows the RPC header.
  *
- * This function returns 1 to indicate success. The data is not yet in
+ * This function returns:
+ * 0 - No error and no read-list found.
+ *
+ * 1 - Successful read-list processing. The data is not yet in
  * the pagelist and therefore the RPC request must be deferred. The
  * I/O completion will enqueue the transport again and
  * svc_rdma_recvfrom will complete the request.
  *
+ * <0 - Error processing/posting read-list.
+ *
  * NOTE: The ctxt must not be touched after the last WR has been posted
  * because the I/O completion processing may occur on another
  * processor and free / modify the context. Ne touche pas!
@@ -398,7 +403,7 @@ next_sge:
                        svc_rdma_put_context(head, 1);
                        head = ctxt;
                }
-               return 0;
+               return err;
        }
 
        return 1;
@@ -532,14 +537,18 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
                goto close_out;
        }
 
-       /* Read read-list data. If we would need to wait, defer
-        * it. Not that in this case, we don't return the RQ credit
-        * until after the read completes.
-        */
-       if (rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt)) {
+       /* Read read-list data. */
+       ret = rdma_read_xdr(rdma_xprt, rmsgp, rqstp, ctxt);
+       if (ret > 0) {
+               /* read-list posted, defer until data received from client. */
                svc_xprt_received(xprt);
                return 0;
        }
+       if (ret < 0) {
+               /* Post of read-list failed, free context. */
+               svc_rdma_put_context(ctxt, 1);
+               return 0;
+       }
 
        ret = rqstp->rq_arg.head[0].iov_len
                + rqstp->rq_arg.page_len