xprtrdma: Decode credits field in rpcrdma_reply_handler
authorChuck Lever <chuck.lever@oracle.com>
Mon, 16 Oct 2017 19:01:39 +0000 (15:01 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 17 Nov 2017 18:47:55 +0000 (13:47 -0500)
We need to decode and save the incoming rdma_credits field _after_
we know that the direction of the message is "forward direction
Reply". Otherwise, the credits value in reverse direction Calls is
also used to update the forward direction credits.

It is safe to decode the rdma_credits field in rpcrdma_reply_handler
now that rpcrdma_reply_handler is single-threaded. Receives complete
in the same order as they were sent on the NFS server.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h

index 430f8b5a8c43152c702b8c9ad79e2544eadc32d6..b8818c09a621f6a0bd141e5f57ab78c00b829e26 100644 (file)
@@ -1244,7 +1244,7 @@ void rpcrdma_complete_rqst(struct rpcrdma_rep *rep)
 out:
        spin_lock(&xprt->recv_lock);
        cwnd = xprt->cwnd;
-       xprt->cwnd = atomic_read(&r_xprt->rx_buf.rb_credits) << RPC_CWNDSHIFT;
+       xprt->cwnd = r_xprt->rx_buf.rb_credits << RPC_CWNDSHIFT;
        if (xprt->cwnd > cwnd)
                xprt_release_rqst_cong(rqst->rq_task);
 
@@ -1297,8 +1297,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
 {
        struct rpcrdma_xprt *r_xprt = rep->rr_rxprt;
        struct rpc_xprt *xprt = &r_xprt->rx_xprt;
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
        struct rpcrdma_req *req;
        struct rpc_rqst *rqst;
+       u32 credits;
        __be32 *p;
 
        dprintk("RPC:       %s: incoming rep %p\n", __func__, rep);
@@ -1315,7 +1317,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
                goto out_shortreply;
        rep->rr_xid = *p++;
        rep->rr_vers = *p++;
-       p++;    /* credits */
+       credits = be32_to_cpu(*p++);
        rep->rr_proc = *p++;
 
        if (rep->rr_vers != rpcrdma_version)
@@ -1332,7 +1334,15 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
        if (!rqst)
                goto out_norqst;
        xprt_pin_rqst(rqst);
+
+       if (credits == 0)
+               credits = 1;    /* don't deadlock */
+       else if (credits > buf->rb_max_requests)
+               credits = buf->rb_max_requests;
+       buf->rb_credits = credits;
+
        spin_unlock(&xprt->recv_lock);
+
        req = rpcr_to_rdmar(rqst);
        req->rl_reply = rep;
        rep->rr_rqst = rqst;
index d45695408df3b4d7ab70bc6bc90f0dc738cf03e6..247b00b715c293c95e7b407312c4b50590c92ad7 100644 (file)
@@ -133,25 +133,6 @@ rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
                       wc->status, wc->vendor_err);
 }
 
-/* Perform basic sanity checking to avoid using garbage
- * to update the credit grant value.
- */
-static void
-rpcrdma_update_granted_credits(struct rpcrdma_rep *rep)
-{
-       struct rpcrdma_buffer *buffer = &rep->rr_rxprt->rx_buf;
-       __be32 *p = rep->rr_rdmabuf->rg_base;
-       u32 credits;
-
-       credits = be32_to_cpup(p + 2);
-       if (credits == 0)
-               credits = 1;    /* don't deadlock */
-       else if (credits > buffer->rb_max_requests)
-               credits = buffer->rb_max_requests;
-
-       atomic_set(&buffer->rb_credits, credits);
-}
-
 /**
  * rpcrdma_wc_receive - Invoked by RDMA provider for each polled Receive WC
  * @cq:        completion queue (ignored)
@@ -181,9 +162,6 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
                                   rdmab_addr(rep->rr_rdmabuf),
                                   wc->byte_len, DMA_FROM_DEVICE);
 
-       if (wc->byte_len >= RPCRDMA_HDRLEN_ERR)
-               rpcrdma_update_granted_credits(rep);
-
 out_schedule:
        rpcrdma_reply_handler(rep);
        return;
@@ -295,7 +273,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
        case RDMA_CM_EVENT_DISCONNECTED:
                connstate = -ECONNABORTED;
 connected:
-               atomic_set(&xprt->rx_buf.rb_credits, 1);
+               xprt->rx_buf.rb_credits = 1;
                ep->rep_connected = connstate;
                rpcrdma_conn_func(ep);
                wake_up_all(&ep->rep_connect_wait);
@@ -995,7 +973,6 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
 
        buf->rb_max_requests = r_xprt->rx_data.max_requests;
        buf->rb_bc_srv_max_requests = 0;
-       atomic_set(&buf->rb_credits, 1);
        spin_lock_init(&buf->rb_mwlock);
        spin_lock_init(&buf->rb_lock);
        spin_lock_init(&buf->rb_recovery_lock);
index a85bcd19b37aeee839d078f07526d5326d06ad3c..0e0ae6195a5bd493413c88699ade78481acc88ef 100644 (file)
@@ -407,7 +407,7 @@ struct rpcrdma_buffer {
        struct list_head        rb_send_bufs;
        struct list_head        rb_recv_bufs;
        u32                     rb_max_requests;
-       atomic_t                rb_credits;     /* most recent credit grant */
+       u32                     rb_credits;     /* most recent credit grant */
 
        u32                     rb_bc_srv_max_requests;
        spinlock_t              rb_reqslock;    /* protect rb_allreqs */