| From 3cd7ca15b8c31063269d6c1d05c912870a5b55de Mon Sep 17 00:00:00 2001 |
| From: Chuck Lever <chuck.lever@oracle.com> |
| Date: Wed, 9 Oct 2019 13:07:38 -0400 |
| Subject: [PATCH] xprtrdma: Close window between waking RPC senders and posting |
| Receives |
| |
| commit 2ae50ad68cd79224198b525f7bd645c9da98b6ff upstream. |
| |
| A recent clean up attempted to separate Receive handling and RPC |
| Reply processing, in the name of clean layering. |
| |
| Unfortunately, we can't do this because the Receive Queue has to be |
| refilled _after_ the most recent credit update from the responder |
| is parsed from the transport header, but _before_ we wake up the |
| next RPC sender. That is right in the middle of |
| rpcrdma_reply_handler(). |
| |
| Usually this isn't a problem because current responder |
| implementations don't vary their credit grant. The one exception is |
| when a connection is established: the grant goes from one to a much |
| larger number on the first Receive. The requester MUST post enough |
| Receives right then so that any outstanding requests can be sent |
| without risking RNR and connection loss. |
| |
| Fixes: 6ceea36890a0 ("xprtrdma: Refactor Receive accounting") |
| Signed-off-by: Chuck Lever <chuck.lever@oracle.com> |
| Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c |
| index 85115a2e2639..6d70cd45ef0b 100644 |
| --- a/net/sunrpc/xprtrdma/rpc_rdma.c |
| +++ b/net/sunrpc/xprtrdma/rpc_rdma.c |
| @@ -1365,6 +1365,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) |
| xprt->cwnd = credits << RPC_CWNDSHIFT; |
| spin_unlock_bh(&xprt->transport_lock); |
| } |
| + rpcrdma_post_recvs(r_xprt, false); |
| |
| req = rpcr_to_rdmar(rqst); |
| if (req->rl_reply) { |
| diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c |
| index 3f67c395845d..c07462946ecb 100644 |
| --- a/net/sunrpc/xprtrdma/verbs.c |
| +++ b/net/sunrpc/xprtrdma/verbs.c |
| @@ -81,7 +81,6 @@ rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction, |
| gfp_t flags); |
| static void rpcrdma_regbuf_dma_unmap(struct rpcrdma_regbuf *rb); |
| static void rpcrdma_regbuf_free(struct rpcrdma_regbuf *rb); |
| -static void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp); |
| |
| /* Wait for outstanding transport work to finish. ib_drain_qp |
| * handles the drains in the wrong order for us, so open code |
| @@ -169,7 +168,6 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) |
| rdmab_addr(rep->rr_rdmabuf), |
| wc->byte_len, DMA_FROM_DEVICE); |
| |
| - rpcrdma_post_recvs(r_xprt, false); |
| rpcrdma_reply_handler(rep); |
| return; |
| |
| @@ -1502,8 +1500,13 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia, |
| return 0; |
| } |
| |
| -static void |
| -rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp) |
| +/** |
| + * rpcrdma_post_recvs - Refill the Receive Queue |
| + * @r_xprt: controlling transport instance |
| + * @temp: mark Receive buffers to be deleted after use |
| + * |
| + */ |
| +void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp) |
| { |
| struct rpcrdma_buffer *buf = &r_xprt->rx_buf; |
| struct rpcrdma_ep *ep = &r_xprt->rx_ep; |
| diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h |
| index d1e0749bcbc4..6554f89ebaa1 100644 |
| --- a/net/sunrpc/xprtrdma/xprt_rdma.h |
| +++ b/net/sunrpc/xprtrdma/xprt_rdma.h |
| @@ -496,6 +496,7 @@ void rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *); |
| |
| int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, |
| struct rpcrdma_req *); |
| +void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp); |
| |
| /* |
| * Buffer calls - xprtrdma/verbs.c |
| -- |
| 2.7.4 |
| |