Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d16d4009 authored by Tom Tucker's avatar Tom Tucker
Browse files

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: default avatarTom Tucker <tom@opengridcomputing.com>
parent 58e8f621
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -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