svcrdma: Avoid Send Queue overflow
authorChuck Lever <chuck.lever@oracle.com>
Fri, 23 Jun 2017 21:17:24 +0000 (17:17 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 28 Jun 2017 18:21:43 +0000 (14:21 -0400)
Sanity case: Catch the case where more Work Requests are being
posted to the Send Queue than there are Send Queue Entries.

This might happen if a client sends a chunk with more segments than
there are SQEs for the transport. The server can't send that reply,
so the transport will deadlock unless the client drops the RPC.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
net/sunrpc/xprtrdma/svc_rdma_rw.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c

index 0cf6202..3b35364 100644 (file)
@@ -232,6 +232,9 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
        struct ib_cqe *cqe;
        int ret;
 
+       if (cc->cc_sqecount > rdma->sc_sq_depth)
+               return -EINVAL;
+
        first_wr = NULL;
        cqe = &cc->cc_cqe;
        list_for_each(tmp, &cc->cc_rwctxts) {
@@ -425,6 +428,7 @@ static int svc_rdma_send_xdr_pagelist(struct svc_rdma_write_info *info,
  *
  * Returns a non-negative number of bytes the chunk consumed, or
  *     %-E2BIG if the payload was larger than the Write chunk,
+ *     %-EINVAL if client provided too many segments,
  *     %-ENOMEM if rdma_rw context pool was exhausted,
  *     %-ENOTCONN if posting failed (connection is lost),
  *     %-EIO if rdma_rw initialization failed (DMA mapping, etc).
@@ -465,6 +469,7 @@ out_err:
  *
  * Returns a non-negative number of bytes the chunk consumed, or
  *     %-E2BIG if the payload was larger than the Reply chunk,
+ *     %-EINVAL if client provided too many segments,
  *     %-ENOMEM if rdma_rw context pool was exhausted,
  *     %-ENOTCONN if posting failed (connection is lost),
  *     %-EIO if rdma_rw initialization failed (DMA mapping, etc).
index 5ba6d91..19fd01e 100644 (file)
@@ -684,7 +684,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        return 0;
 
  err2:
-       if (ret != -E2BIG)
+       if (ret != -E2BIG || ret != -EINVAL)
                goto err1;
 
        ret = svc_rdma_post_recv(rdma, GFP_KERNEL);