> On May 8, 2018, at 3:52 PM, Anna Schumaker <Anna.Schumaker@xxxxxxxxxx> wrote: > > > > On 05/08/2018 03:47 PM, Chuck Lever wrote: >> >> >>> On May 8, 2018, at 3:40 PM, Anna Schumaker <anna.schumaker@xxxxxxxxxx> wrote: >>> >>> Hi Chuck, >>> >>> On 05/04/2018 03:35 PM, Chuck Lever wrote: >>>> Receive completion and Reply handling are done by a BOUND >>>> workqueue, meaning they run on only one CPU. >>>> >>>> Posting receives is currently done in the send_request path, which >>>> on large systems is typically done on a different CPU than the one >>>> handling Receive completions. This results in movement of >>>> Receive-related cachelines between the sending and receiving CPUs. >>>> >>>> More importantly, it means that currently Receives are posted while >>>> the transport's write lock is held, which is unnecessary and costly. >>>> >>>> Finally, allocation of Receive buffers is performed on-demand in >>>> the Receive completion handler. This helps guarantee that they are >>>> allocated on the same NUMA node as the CPU that handles Receive >>>> completions. >>>> >>>> Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> >>> >>> Running this against a 4.17-rc4 server seems to work okay, but running against a 4.16 server fails the cthon special tests with: >>> >>> write/read 30 MB file >>> verify failed, offset 11272192; expected 79, got >>> 79 79 79 79 79 79 79 79 79 79 >>> 79 79 79 79 79 79 79 79 79 79 >>> 79 79 79 79 79 79 79 79 79 79 >>> 79 79 79 79 79 79 79 79 79 79 >>> 79 79 79 79 79 79 79 79 79 79 >>> 79 79 79 79 79 79 79 79 79 79 >>> >>> and it goes on for several hundred more lines after this. How worried do we need to be about somebody running a new client against and old server? >> >> I'm not sure what that result means, I've never seen it >> before. But I can't think of a reason there would be an >> incompatibility with a v4.16 server. That behavior needs >> to be chased down and explained. >> >> Can you bisect this to a particular commit? > > Do you mean on the server side? I don't see the problem on the client until I apply this patch Sure, why not try bisecting the server. I'll see if I can reproduce the behavior here with InfiniBand. >>> Some of the performance issues I've had in the past seem to have gone away with the 4.17-rc4 code as well. I'm not sure if that's related to your code or something changing in soft roce, but either way I'm much happier :) >>> >>> Anna >>> >>>> --- >>>> include/trace/events/rpcrdma.h | 40 +++++++- >>>> net/sunrpc/xprtrdma/backchannel.c | 32 +------ >>>> net/sunrpc/xprtrdma/rpc_rdma.c | 22 +---- >>>> net/sunrpc/xprtrdma/transport.c | 3 - >>>> net/sunrpc/xprtrdma/verbs.c | 176 +++++++++++++++++++++---------------- >>>> net/sunrpc/xprtrdma/xprt_rdma.h | 6 + >>>> 6 files changed, 150 insertions(+), 129 deletions(-) >>>> >>>> diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h >>>> index 99c0049..ad27e19 100644 >>>> --- a/include/trace/events/rpcrdma.h >>>> +++ b/include/trace/events/rpcrdma.h >>>> @@ -546,6 +546,39 @@ >>>> ) >>>> ); >>>> >>>> +TRACE_EVENT(xprtrdma_post_recvs, >>>> + TP_PROTO( >>>> + const struct rpcrdma_xprt *r_xprt, >>>> + unsigned int count, >>>> + int status >>>> + ), >>>> + >>>> + TP_ARGS(r_xprt, count, status), >>>> + >>>> + TP_STRUCT__entry( >>>> + __field(const void *, r_xprt) >>>> + __field(unsigned int, count) >>>> + __field(int, status) >>>> + __field(int, posted) >>>> + __string(addr, rpcrdma_addrstr(r_xprt)) >>>> + __string(port, rpcrdma_portstr(r_xprt)) >>>> + ), >>>> + >>>> + TP_fast_assign( >>>> + __entry->r_xprt = r_xprt; >>>> + __entry->count = count; >>>> + __entry->status = status; >>>> + __entry->posted = r_xprt->rx_buf.rb_posted_receives; >>>> + __assign_str(addr, rpcrdma_addrstr(r_xprt)); >>>> + __assign_str(port, rpcrdma_portstr(r_xprt)); >>>> + ), >>>> + >>>> + TP_printk("peer=[%s]:%s r_xprt=%p: %u new recvs, %d active (rc %d)", >>>> + __get_str(addr), __get_str(port), __entry->r_xprt, >>>> + __entry->count, __entry->posted, __entry->status >>>> + ) >>>> +); >>>> + >>>> /** >>>> ** Completion events >>>> **/ >>>> @@ -800,7 +833,6 @@ >>>> __field(unsigned int, task_id) >>>> __field(unsigned int, client_id) >>>> __field(const void *, req) >>>> - __field(const void *, rep) >>>> __field(size_t, callsize) >>>> __field(size_t, rcvsize) >>>> ), >>>> @@ -809,15 +841,13 @@ >>>> __entry->task_id = task->tk_pid; >>>> __entry->client_id = task->tk_client->cl_clid; >>>> __entry->req = req; >>>> - __entry->rep = req ? req->rl_reply : NULL; >>>> __entry->callsize = task->tk_rqstp->rq_callsize; >>>> __entry->rcvsize = task->tk_rqstp->rq_rcvsize; >>>> ), >>>> >>>> - TP_printk("task:%u@%u req=%p rep=%p (%zu, %zu)", >>>> + TP_printk("task:%u@%u req=%p (%zu, %zu)", >>>> __entry->task_id, __entry->client_id, >>>> - __entry->req, __entry->rep, >>>> - __entry->callsize, __entry->rcvsize >>>> + __entry->req, __entry->callsize, __entry->rcvsize >>>> ) >>>> ); >>>> >>>> diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c >>>> index 4034788..c8f1c2b 100644 >>>> --- a/net/sunrpc/xprtrdma/backchannel.c >>>> +++ b/net/sunrpc/xprtrdma/backchannel.c >>>> @@ -71,23 +71,6 @@ static int rpcrdma_bc_setup_reqs(struct rpcrdma_xprt *r_xprt, >>>> return -ENOMEM; >>>> } >>>> >>>> -/* Allocate and add receive buffers to the rpcrdma_buffer's >>>> - * existing list of rep's. These are released when the >>>> - * transport is destroyed. >>>> - */ >>>> -static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt, >>>> - unsigned int count) >>>> -{ >>>> - int rc = 0; >>>> - >>>> - while (count--) { >>>> - rc = rpcrdma_create_rep(r_xprt); >>>> - if (rc) >>>> - break; >>>> - } >>>> - return rc; >>>> -} >>>> - >>>> /** >>>> * xprt_rdma_bc_setup - Pre-allocate resources for handling backchannel requests >>>> * @xprt: transport associated with these backchannel resources >>>> @@ -116,14 +99,6 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs) >>>> if (rc) >>>> goto out_free; >>>> >>>> - rc = rpcrdma_bc_setup_reps(r_xprt, reqs); >>>> - if (rc) >>>> - goto out_free; >>>> - >>>> - rc = rpcrdma_ep_post_extra_recv(r_xprt, reqs); >>>> - if (rc) >>>> - goto out_free; >>>> - >>>> r_xprt->rx_buf.rb_bc_srv_max_requests = reqs; >>>> request_module("svcrdma"); >>>> trace_xprtrdma_cb_setup(r_xprt, reqs); >>>> @@ -228,6 +203,7 @@ int xprt_rdma_bc_send_reply(struct rpc_rqst *rqst) >>>> if (rc < 0) >>>> goto failed_marshal; >>>> >>>> + rpcrdma_post_recvs(r_xprt, true); >>>> if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) >>>> goto drop_connection; >>>> return 0; >>>> @@ -268,10 +244,14 @@ void xprt_rdma_bc_destroy(struct rpc_xprt *xprt, unsigned int reqs) >>>> */ >>>> void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst) >>>> { >>>> + struct rpcrdma_req *req = rpcr_to_rdmar(rqst); >>>> struct rpc_xprt *xprt = rqst->rq_xprt; >>>> >>>> dprintk("RPC: %s: freeing rqst %p (req %p)\n", >>>> - __func__, rqst, rpcr_to_rdmar(rqst)); >>>> + __func__, rqst, req); >>>> + >>>> + rpcrdma_recv_buffer_put(req->rl_reply); >>>> + req->rl_reply = NULL; >>>> >>>> spin_lock_bh(&xprt->bc_pa_lock); >>>> list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list); >>>> diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c >>>> index 8f89e3f..d676106 100644 >>>> --- a/net/sunrpc/xprtrdma/rpc_rdma.c >>>> +++ b/net/sunrpc/xprtrdma/rpc_rdma.c >>>> @@ -1027,8 +1027,6 @@ static bool rpcrdma_results_inline(struct rpcrdma_xprt *r_xprt, >>>> >>>> out_short: >>>> pr_warn("RPC/RDMA short backward direction call\n"); >>>> - if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep)) >>>> - xprt_disconnect_done(&r_xprt->rx_xprt); >>>> return true; >>>> } >>>> #else /* CONFIG_SUNRPC_BACKCHANNEL */ >>>> @@ -1334,13 +1332,14 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) >>>> u32 credits; >>>> __be32 *p; >>>> >>>> + --buf->rb_posted_receives; >>>> + >>>> if (rep->rr_hdrbuf.head[0].iov_len == 0) >>>> goto out_badstatus; >>>> >>>> + /* Fixed transport header fields */ >>>> xdr_init_decode(&rep->rr_stream, &rep->rr_hdrbuf, >>>> rep->rr_hdrbuf.head[0].iov_base); >>>> - >>>> - /* Fixed transport header fields */ >>>> p = xdr_inline_decode(&rep->rr_stream, 4 * sizeof(*p)); >>>> if (unlikely(!p)) >>>> goto out_shortreply; >>>> @@ -1379,17 +1378,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) >>>> >>>> trace_xprtrdma_reply(rqst->rq_task, rep, req, credits); >>>> >>>> + rpcrdma_post_recvs(r_xprt, false); >>>> queue_work(rpcrdma_receive_wq, &rep->rr_work); >>>> return; >>>> >>>> -out_badstatus: >>>> - rpcrdma_recv_buffer_put(rep); >>>> - if (r_xprt->rx_ep.rep_connected == 1) { >>>> - r_xprt->rx_ep.rep_connected = -EIO; >>>> - rpcrdma_conn_func(&r_xprt->rx_ep); >>>> - } >>>> - return; >>>> - >>>> out_badversion: >>>> trace_xprtrdma_reply_vers(rep); >>>> goto repost; >>>> @@ -1409,7 +1401,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) >>>> * receive buffer before returning. >>>> */ >>>> repost: >>>> - r_xprt->rx_stats.bad_reply_count++; >>>> - if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep)) >>>> - rpcrdma_recv_buffer_put(rep); >>>> + rpcrdma_post_recvs(r_xprt, false); >>>> +out_badstatus: >>>> + rpcrdma_recv_buffer_put(rep); >>>> } >>>> diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c >>>> index 79885aa..0c775f0 100644 >>>> --- a/net/sunrpc/xprtrdma/transport.c >>>> +++ b/net/sunrpc/xprtrdma/transport.c >>>> @@ -722,9 +722,6 @@ >>>> if (rc < 0) >>>> goto failed_marshal; >>>> >>>> - if (req->rl_reply == NULL) /* e.g. reconnection */ >>>> - rpcrdma_recv_buffer_get(req); >>>> - >>>> /* Must suppress retransmit to maintain credits */ >>>> if (rqst->rq_connect_cookie == xprt->connect_cookie) >>>> goto drop_connection; >>>> diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c >>>> index f4ce7af..2a38301 100644 >>>> --- a/net/sunrpc/xprtrdma/verbs.c >>>> +++ b/net/sunrpc/xprtrdma/verbs.c >>>> @@ -74,6 +74,7 @@ >>>> */ >>>> static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt); >>>> static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf); >>>> +static int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp); >>>> static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb); >>>> >>>> struct workqueue_struct *rpcrdma_receive_wq __read_mostly; >>>> @@ -726,7 +727,6 @@ >>>> { >>>> struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt, >>>> rx_ia); >>>> - unsigned int extras; >>>> int rc; >>>> >>>> retry: >>>> @@ -770,9 +770,8 @@ >>>> } >>>> >>>> dprintk("RPC: %s: connected\n", __func__); >>>> - extras = r_xprt->rx_buf.rb_bc_srv_max_requests; >>>> - if (extras) >>>> - rpcrdma_ep_post_extra_recv(r_xprt, extras); >>>> + >>>> + rpcrdma_post_recvs(r_xprt, true); >>>> >>>> out: >>>> if (rc) >>>> @@ -1082,14 +1081,8 @@ struct rpcrdma_req * >>>> return req; >>>> } >>>> >>>> -/** >>>> - * rpcrdma_create_rep - Allocate an rpcrdma_rep object >>>> - * @r_xprt: controlling transport >>>> - * >>>> - * Returns 0 on success or a negative errno on failure. >>>> - */ >>>> -int >>>> -rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt) >>>> +static int >>>> +rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp) >>>> { >>>> struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data; >>>> struct rpcrdma_buffer *buf = &r_xprt->rx_buf; >>>> @@ -1117,6 +1110,7 @@ struct rpcrdma_req * >>>> rep->rr_recv_wr.wr_cqe = &rep->rr_cqe; >>>> rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov; >>>> rep->rr_recv_wr.num_sge = 1; >>>> + rep->rr_temp = temp; >>>> >>>> spin_lock(&buf->rb_lock); >>>> list_add(&rep->rr_list, &buf->rb_recv_bufs); >>>> @@ -1168,12 +1162,8 @@ struct rpcrdma_req * >>>> list_add(&req->rl_list, &buf->rb_send_bufs); >>>> } >>>> >>>> + buf->rb_posted_receives = 0; >>>> INIT_LIST_HEAD(&buf->rb_recv_bufs); >>>> - for (i = 0; i <= buf->rb_max_requests; i++) { >>>> - rc = rpcrdma_create_rep(r_xprt); >>>> - if (rc) >>>> - goto out; >>>> - } >>>> >>>> rc = rpcrdma_sendctxs_create(r_xprt); >>>> if (rc) >>>> @@ -1268,7 +1258,6 @@ struct rpcrdma_req * >>>> rep = rpcrdma_buffer_get_rep_locked(buf); >>>> rpcrdma_destroy_rep(rep); >>>> } >>>> - buf->rb_send_count = 0; >>>> >>>> spin_lock(&buf->rb_reqslock); >>>> while (!list_empty(&buf->rb_allreqs)) { >>>> @@ -1283,7 +1272,6 @@ struct rpcrdma_req * >>>> spin_lock(&buf->rb_reqslock); >>>> } >>>> spin_unlock(&buf->rb_reqslock); >>>> - buf->rb_recv_count = 0; >>>> >>>> rpcrdma_mrs_destroy(buf); >>>> } >>>> @@ -1356,27 +1344,11 @@ struct rpcrdma_mr * >>>> __rpcrdma_mr_put(&r_xprt->rx_buf, mr); >>>> } >>>> >>>> -static struct rpcrdma_rep * >>>> -rpcrdma_buffer_get_rep(struct rpcrdma_buffer *buffers) >>>> -{ >>>> - /* If an RPC previously completed without a reply (say, a >>>> - * credential problem or a soft timeout occurs) then hold off >>>> - * on supplying more Receive buffers until the number of new >>>> - * pending RPCs catches up to the number of posted Receives. >>>> - */ >>>> - if (unlikely(buffers->rb_send_count < buffers->rb_recv_count)) >>>> - return NULL; >>>> - >>>> - if (unlikely(list_empty(&buffers->rb_recv_bufs))) >>>> - return NULL; >>>> - buffers->rb_recv_count++; >>>> - return rpcrdma_buffer_get_rep_locked(buffers); >>>> -} >>>> - >>>> -/* >>>> - * Get a set of request/reply buffers. >>>> +/** >>>> + * rpcrdma_buffer_get - Get a request buffer >>>> + * @buffers: Buffer pool from which to obtain a buffer >>>> * >>>> - * Reply buffer (if available) is attached to send buffer upon return. >>>> + * Returns a fresh rpcrdma_req, or NULL if none are available. >>>> */ >>>> struct rpcrdma_req * >>>> rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) >>>> @@ -1384,23 +1356,21 @@ struct rpcrdma_req * >>>> struct rpcrdma_req *req; >>>> >>>> spin_lock(&buffers->rb_lock); >>>> - if (list_empty(&buffers->rb_send_bufs)) >>>> - goto out_reqbuf; >>>> - buffers->rb_send_count++; >>>> + if (unlikely(list_empty(&buffers->rb_send_bufs))) >>>> + goto out_noreqs; >>>> req = rpcrdma_buffer_get_req_locked(buffers); >>>> - req->rl_reply = rpcrdma_buffer_get_rep(buffers); >>>> spin_unlock(&buffers->rb_lock); >>>> - >>>> return req; >>>> >>>> -out_reqbuf: >>>> +out_noreqs: >>>> spin_unlock(&buffers->rb_lock); >>>> return NULL; >>>> } >>>> >>>> -/* >>>> - * Put request/reply buffers back into pool. >>>> - * Pre-decrement counter/array index. >>>> +/** >>>> + * rpcrdma_buffer_put - Put request/reply buffers back into pool >>>> + * @req: object to return >>>> + * >>>> */ >>>> void >>>> rpcrdma_buffer_put(struct rpcrdma_req *req) >>>> @@ -1411,27 +1381,16 @@ struct rpcrdma_req * >>>> req->rl_reply = NULL; >>>> >>>> spin_lock(&buffers->rb_lock); >>>> - buffers->rb_send_count--; >>>> - list_add_tail(&req->rl_list, &buffers->rb_send_bufs); >>>> + list_add(&req->rl_list, &buffers->rb_send_bufs); >>>> if (rep) { >>>> - buffers->rb_recv_count--; >>>> - list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs); >>>> + if (!rep->rr_temp) { >>>> + list_add(&rep->rr_list, &buffers->rb_recv_bufs); >>>> + rep = NULL; >>>> + } >>>> } >>>> spin_unlock(&buffers->rb_lock); >>>> -} >>>> - >>>> -/* >>>> - * Recover reply buffers from pool. >>>> - * This happens when recovering from disconnect. >>>> - */ >>>> -void >>>> -rpcrdma_recv_buffer_get(struct rpcrdma_req *req) >>>> -{ >>>> - struct rpcrdma_buffer *buffers = req->rl_buffer; >>>> - >>>> - spin_lock(&buffers->rb_lock); >>>> - req->rl_reply = rpcrdma_buffer_get_rep(buffers); >>>> - spin_unlock(&buffers->rb_lock); >>>> + if (rep) >>>> + rpcrdma_destroy_rep(rep); >>>> } >>>> >>>> /* >>>> @@ -1443,10 +1402,13 @@ struct rpcrdma_req * >>>> { >>>> struct rpcrdma_buffer *buffers = &rep->rr_rxprt->rx_buf; >>>> >>>> - spin_lock(&buffers->rb_lock); >>>> - buffers->rb_recv_count--; >>>> - list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs); >>>> - spin_unlock(&buffers->rb_lock); >>>> + if (!rep->rr_temp) { >>>> + spin_lock(&buffers->rb_lock); >>>> + list_add(&rep->rr_list, &buffers->rb_recv_bufs); >>>> + spin_unlock(&buffers->rb_lock); >>>> + } else { >>>> + rpcrdma_destroy_rep(rep); >>>> + } >>>> } >>>> >>>> /** >>>> @@ -1542,13 +1504,6 @@ struct rpcrdma_regbuf * >>>> struct ib_send_wr *send_wr = &req->rl_sendctx->sc_wr; >>>> int rc; >>>> >>>> - if (req->rl_reply) { >>>> - rc = rpcrdma_ep_post_recv(ia, req->rl_reply); >>>> - if (rc) >>>> - return rc; >>>> - req->rl_reply = NULL; >>>> - } >>>> - >>>> if (!ep->rep_send_count || >>>> test_bit(RPCRDMA_REQ_F_TX_RESOURCES, &req->rl_flags)) { >>>> send_wr->send_flags |= IB_SEND_SIGNALED; >>>> @@ -1623,3 +1578,70 @@ struct rpcrdma_regbuf * >>>> rpcrdma_recv_buffer_put(rep); >>>> return rc; >>>> } >>>> + >>>> +/** >>>> + * rpcrdma_post_recvs - Maybe post some Receive buffers >>>> + * @r_xprt: controlling transport >>>> + * @temp: when true, allocate temp rpcrdma_rep objects >>>> + * >>>> + */ >>>> +void >>>> +rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp) >>>> +{ >>>> + struct rpcrdma_buffer *buf = &r_xprt->rx_buf; >>>> + struct ib_recv_wr *wr, *bad_wr; >>>> + int needed, count, rc; >>>> + >>>> + needed = buf->rb_credits + (buf->rb_bc_srv_max_requests << 1); >>>> + if (buf->rb_posted_receives > needed) >>>> + return; >>>> + needed -= buf->rb_posted_receives; >>>> + >>>> + count = 0; >>>> + wr = NULL; >>>> + while (needed) { >>>> + struct rpcrdma_regbuf *rb; >>>> + struct rpcrdma_rep *rep; >>>> + >>>> + spin_lock(&buf->rb_lock); >>>> + rep = list_first_entry_or_null(&buf->rb_recv_bufs, >>>> + struct rpcrdma_rep, rr_list); >>>> + if (likely(rep)) >>>> + list_del(&rep->rr_list); >>>> + spin_unlock(&buf->rb_lock); >>>> + if (!rep) { >>>> + if (rpcrdma_create_rep(r_xprt, temp)) >>>> + break; >>>> + continue; >>>> + } >>>> + >>>> + rb = rep->rr_rdmabuf; >>>> + if (!rpcrdma_regbuf_is_mapped(rb)) { >>>> + if (!__rpcrdma_dma_map_regbuf(&r_xprt->rx_ia, rb)) { >>>> + rpcrdma_recv_buffer_put(rep); >>>> + break; >>>> + } >>>> + } >>>> + >>>> + trace_xprtrdma_post_recv(rep->rr_recv_wr.wr_cqe); >>>> + rep->rr_recv_wr.next = wr; >>>> + wr = &rep->rr_recv_wr; >>>> + ++count; >>>> + --needed; >>>> + } >>>> + if (!count) >>>> + return; >>>> + >>>> + rc = ib_post_recv(r_xprt->rx_ia.ri_id->qp, wr, &bad_wr); >>>> + if (rc) { >>>> + for (wr = bad_wr; wr; wr = wr->next) { >>>> + struct rpcrdma_rep *rep; >>>> + >>>> + rep = container_of(wr, struct rpcrdma_rep, rr_recv_wr); >>>> + rpcrdma_recv_buffer_put(rep); >>>> + --count; >>>> + } >>>> + } >>>> + buf->rb_posted_receives += count; >>>> + trace_xprtrdma_post_recvs(r_xprt, count, rc); >>>> +} >>>> diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h >>>> index 765e4df..a6d0d6e 100644 >>>> --- a/net/sunrpc/xprtrdma/xprt_rdma.h >>>> +++ b/net/sunrpc/xprtrdma/xprt_rdma.h >>>> @@ -197,6 +197,7 @@ struct rpcrdma_rep { >>>> __be32 rr_proc; >>>> int rr_wc_flags; >>>> u32 rr_inv_rkey; >>>> + bool rr_temp; >>>> struct rpcrdma_regbuf *rr_rdmabuf; >>>> struct rpcrdma_xprt *rr_rxprt; >>>> struct work_struct rr_work; >>>> @@ -397,11 +398,11 @@ struct rpcrdma_buffer { >>>> struct rpcrdma_sendctx **rb_sc_ctxs; >>>> >>>> spinlock_t rb_lock; /* protect buf lists */ >>>> - int rb_send_count, rb_recv_count; >>>> struct list_head rb_send_bufs; >>>> struct list_head rb_recv_bufs; >>>> u32 rb_max_requests; >>>> u32 rb_credits; /* most recent credit grant */ >>>> + int rb_posted_receives; >>>> >>>> u32 rb_bc_srv_max_requests; >>>> spinlock_t rb_reqslock; /* protect rb_allreqs */ >>>> @@ -558,13 +559,13 @@ int rpcrdma_ep_create(struct rpcrdma_ep *, struct rpcrdma_ia *, >>>> int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, >>>> struct rpcrdma_req *); >>>> int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_rep *); >>>> +void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp); >>>> >>>> /* >>>> * Buffer calls - xprtrdma/verbs.c >>>> */ >>>> struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *); >>>> void rpcrdma_destroy_req(struct rpcrdma_req *); >>>> -int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt); >>>> int rpcrdma_buffer_create(struct rpcrdma_xprt *); >>>> void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); >>>> struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf); >>>> @@ -577,7 +578,6 @@ int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, >>>> >>>> struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); >>>> void rpcrdma_buffer_put(struct rpcrdma_req *); >>>> -void rpcrdma_recv_buffer_get(struct rpcrdma_req *); >>>> void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); >>>> >>>> struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(size_t, enum dma_data_direction, >>>> >>> -- >>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in >>> the body of a message to majordomo@xxxxxxxxxxxxxxx >>> More majordomo info at http://vger.kernel.org/majordomo-info.html >> >> -- >> Chuck Lever >> >> >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-rdma" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Chuck Lever -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html