SUNRPC: Move svc_xprt_received() call sites
[linux-2.6-microblaze.git] / net / sunrpc / xprtrdma / svc_rdma_recvfrom.c
index 6d28f23..9cb5a09 100644 (file)
 #include "xprt_rdma.h"
 #include <trace/events/rpcrdma.h>
 
-#define RPCDBG_FACILITY        RPCDBG_SVCXPRT
-
 static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc);
 
 static inline struct svc_rdma_recv_ctxt *
@@ -274,6 +272,9 @@ static bool svc_rdma_refresh_recvs(struct svcxprt_rdma *rdma,
        struct ib_recv_wr *recv_chain;
        int ret;
 
+       if (test_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags))
+               return false;
+
        recv_chain = NULL;
        while (wanted--) {
                ctxt = svc_rdma_recv_ctxt_get(rdma);
@@ -291,18 +292,17 @@ static bool svc_rdma_refresh_recvs(struct svcxprt_rdma *rdma,
 
        ret = ib_post_recv(rdma->sc_qp, recv_chain, &bad_wr);
        if (ret)
-               goto err_post;
+               goto err_free;
        return true;
 
-err_post:
+err_free:
+       trace_svcrdma_rq_post_err(rdma, ret);
        while (bad_wr) {
                ctxt = container_of(bad_wr, struct svc_rdma_recv_ctxt,
                                    rc_recv_wr);
                bad_wr = bad_wr->next;
                svc_rdma_recv_ctxt_put(rdma, ctxt);
        }
-
-       trace_svcrdma_rq_post_err(rdma, ret);
        /* Since we're destroying the xprt, no need to reset
         * sc_pending_recvs. */
        return false;
@@ -340,6 +340,19 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
        if (wc->status != IB_WC_SUCCESS)
                goto flushed;
 
+       /* If receive posting fails, the connection is about to be
+        * lost anyway. The server will not be able to send a reply
+        * for this RPC, and the client will retransmit this RPC
+        * anyway when it reconnects.
+        *
+        * Therefore we drop the Receive, even if status was SUCCESS
+        * to reduce the likelihood of replayed requests once the
+        * client reconnects.
+        */
+       if (rdma->sc_pending_recvs < rdma->sc_max_requests)
+               if (!svc_rdma_refresh_recvs(rdma, rdma->sc_recv_batch, false))
+                       goto flushed;
+
        /* All wc fields are now known to be valid */
        ctxt->rc_byte_len = wc->byte_len;
 
@@ -350,20 +363,11 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
        spin_unlock(&rdma->sc_rq_dto_lock);
        if (!test_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags))
                svc_xprt_enqueue(&rdma->sc_xprt);
-
-       if (!test_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags) &&
-           rdma->sc_pending_recvs < rdma->sc_max_requests)
-               if (!svc_rdma_refresh_recvs(rdma, RPCRDMA_MAX_RECV_BATCH,
-                                           false))
-                       goto post_err;
-
        return;
 
 flushed:
        svc_rdma_recv_ctxt_put(rdma, ctxt);
-post_err:
-       set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
-       svc_xprt_enqueue(&rdma->sc_xprt);
+       svc_xprt_deferred_close(&rdma->sc_xprt);
 }
 
 /**
@@ -842,6 +846,7 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
                /* No new incoming requests, terminate the loop */
                clear_bit(XPT_DATA, &xprt->xpt_flags);
                spin_unlock(&rdma_xprt->sc_rq_dto_lock);
+               svc_xprt_received(xprt);
                return 0;
        }
        list_del(&ctxt->rc_list);
@@ -879,28 +884,33 @@ complete:
        rqstp->rq_xprt_ctxt = ctxt;
        rqstp->rq_prot = IPPROTO_MAX;
        svc_xprt_copy_addrs(rqstp, xprt);
+       svc_xprt_received(xprt);
        return rqstp->rq_arg.len;
 
 out_readlist:
        ret = svc_rdma_process_read_list(rdma_xprt, rqstp, ctxt);
        if (ret < 0)
                goto out_readfail;
+       svc_xprt_received(xprt);
        return 0;
 
 out_err:
        svc_rdma_send_error(rdma_xprt, ctxt, ret);
        svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
+       svc_xprt_received(xprt);
        return 0;
 
 out_readfail:
        if (ret == -EINVAL)
                svc_rdma_send_error(rdma_xprt, ctxt, ret);
        svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
+       svc_xprt_received(xprt);
        return ret;
 
 out_backchannel:
        svc_rdma_handle_bc_reply(rqstp, ctxt);
 out_drop:
        svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
+       svc_xprt_received(xprt);
        return 0;
 }