History

Merge tag 'nfs-rdma-for-4.18-1' of git://git.linux-nfs.org/projects/anna/linux-nfs

NFS-over-RDMA client updates for Linux 4.18 Stable patches: - xprtrdma: Return -ENOBUFS when no pages are available New features: - Add ->alloc_slot() and ->free_slot() functions Bugfixes and cleanups: - Add missing SPDX tags to some files - Try to fail mount quickly if client has no RDMA devices - Create transport IDs in the correct network namespace - Fix max_send_wr computation - Clean up receive tracepoints - Refactor receive handling - Remove unused functions

Trond Myklebust committed 8 years ago

Commit fcda3d52 parents 3f0b3cf 11d0ac116 files · +359 −355Browse files

Unified · Split

16 files
  1. include/linux/sunrpc/rpc_rdma.h +1 −0
  2. include/linux/sunrpc/xprt.h +5 −1
  3. include/linux/sunrpc/xprtrdma.h +1 −0
  4. include/trace/events/rpcrdma.h +53 −23
  5. net/sunrpc/clnt.c +1 −0
  6. net/sunrpc/xprt.c +10 −7
  7. net/sunrpc/xprtrdma/backchannel.c +39 −66
  8. net/sunrpc/xprtrdma/fmr_ops.c +23 −0
  9. net/sunrpc/xprtrdma/frwr_ops.c +27 −4
  10. net/sunrpc/xprtrdma/module.c +1 −0
  11. net/sunrpc/xprtrdma/rpc_rdma.c +22 −44
  12. net/sunrpc/xprtrdma/svc_rdma_backchannel.c +1 −0
  13. net/sunrpc/xprtrdma/transport.c +47 −17
  14. net/sunrpc/xprtrdma/verbs.c +112 −179
  15. net/sunrpc/xprtrdma/xprt_rdma.h +12 −14
  16. net/sunrpc/xprtsock.c +4 −0
include/linux/sunrpc/rpc_rdma.h+1−0
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
1/*2/*
2 * Copyright (c) 2015-2017 Oracle. All rights reserved.3 * Copyright (c) 2015-2017 Oracle. All rights reserved.
3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.4 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
include/linux/sunrpc/xprt.h+5−1
@@ -84,7 +84,6 @@ struct rpc_rqst { · 83 unmodified lines
84 void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */84 void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
85 struct list_head rq_list;85 struct list_head rq_list;
86 86
87 void *rq_xprtdata; /* Per-xprt private data */
88 void *rq_buffer; /* Call XDR encode buffer */87 void *rq_buffer; /* Call XDR encode buffer */
89 size_t rq_callsize;88 size_t rq_callsize;
90 void *rq_rbuffer; /* Reply XDR decode buffer */89 void *rq_rbuffer; /* Reply XDR decode buffer */
@@ -127,6 +126,8 @@ struct rpc_xprt_ops { · 36 unmodified lines
127 int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);126 int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
128 void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);127 void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
129 void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task);128 void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task);
129 void (*free_slot)(struct rpc_xprt *xprt,
130 struct rpc_rqst *req);
130 void (*rpcbind)(struct rpc_task *task);131 void (*rpcbind)(struct rpc_task *task);
131 void (*set_port)(struct rpc_xprt *xprt, unsigned short port);132 void (*set_port)(struct rpc_xprt *xprt, unsigned short port);
132 void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);133 void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);
@@ -324,10 +325,13 @@ struct xprt_class { · 191 unmodified lines
324struct rpc_xprt *xprt_create_transport(struct xprt_create *args);325struct rpc_xprt *xprt_create_transport(struct xprt_create *args);
325void xprt_connect(struct rpc_task *task);326void xprt_connect(struct rpc_task *task);
326void xprt_reserve(struct rpc_task *task);327void xprt_reserve(struct rpc_task *task);
328void xprt_request_init(struct rpc_task *task);
327void xprt_retry_reserve(struct rpc_task *task);329void xprt_retry_reserve(struct rpc_task *task);
328int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);330int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
329int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);331int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
330void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);332void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
333void xprt_free_slot(struct rpc_xprt *xprt,
334 struct rpc_rqst *req);
331void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);335void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
332bool xprt_prepare_transmit(struct rpc_task *task);336bool xprt_prepare_transmit(struct rpc_task *task);
333void xprt_transmit(struct rpc_task *task);337void xprt_transmit(struct rpc_task *task);
include/linux/sunrpc/xprtrdma.h+1−0
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
1/*2/*
2 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
3 *4 *
include/trace/events/rpcrdma.h+53−23
@@ -528,24 +528,54 @@ TRACE_EVENT(xprtrdma_post_send, · 527 unmodified lines
528 528
529TRACE_EVENT(xprtrdma_post_recv,529TRACE_EVENT(xprtrdma_post_recv,
530 TP_PROTO(530 TP_PROTO(
531 const struct rpcrdma_rep *rep,531 const struct ib_cqe *cqe
532 ),
533
534 TP_ARGS(cqe),
535
536 TP_STRUCT__entry(
537 __field(const void *, cqe)
538 ),
539
540 TP_fast_assign(
541 __entry->cqe = cqe;
542 ),
543
544 TP_printk("cqe=%p",
545 __entry->cqe
546 )
547);
548
549TRACE_EVENT(xprtrdma_post_recvs,
550 TP_PROTO(
551 const struct rpcrdma_xprt *r_xprt,
552 unsigned int count,
532 int status553 int status
533 ),554 ),
534 555
535 TP_ARGS(rep, status),556 TP_ARGS(r_xprt, count, status),
536 557
537 TP_STRUCT__entry(558 TP_STRUCT__entry(
538 __field(const void *, rep)559 __field(const void *, r_xprt)
560 __field(unsigned int, count)
539 __field(int, status)561 __field(int, status)
562 __field(int, posted)
563 __string(addr, rpcrdma_addrstr(r_xprt))
564 __string(port, rpcrdma_portstr(r_xprt))
540 ),565 ),
541 566
542 TP_fast_assign(567 TP_fast_assign(
543 __entry->rep = rep;568 __entry->r_xprt = r_xprt;
569 __entry->count = count;
544 __entry->status = status;570 __entry->status = status;
571 __entry->posted = r_xprt->rx_buf.rb_posted_receives;
572 __assign_str(addr, rpcrdma_addrstr(r_xprt));
573 __assign_str(port, rpcrdma_portstr(r_xprt));
545 ),574 ),
546 575
547 TP_printk("rep=%p status=%d",576 TP_printk("peer=[%s]:%s r_xprt=%p: %u new recvs, %d active (rc %d)",
548 __entry->rep, __entry->status577 __get_str(addr), __get_str(port), __entry->r_xprt,
578 __entry->count, __entry->posted, __entry->status
549 )579 )
550);580);
551 581
@@ -584,28 +614,32 @@ TRACE_EVENT(xprtrdma_wc_send, · 32 unmodified lines
584 614
585TRACE_EVENT(xprtrdma_wc_receive,615TRACE_EVENT(xprtrdma_wc_receive,
586 TP_PROTO(616 TP_PROTO(
587 const struct rpcrdma_rep *rep,
588 const struct ib_wc *wc617 const struct ib_wc *wc
589 ),618 ),
590 619
591 TP_ARGS(rep, wc),620 TP_ARGS(wc),
592 621
593 TP_STRUCT__entry(622 TP_STRUCT__entry(
594 __field(const void *, rep)623 __field(const void *, cqe)
595 __field(unsigned int, byte_len)624 __field(u32, byte_len)
596 __field(unsigned int, status)625 __field(unsigned int, status)
597 __field(unsigned int, vendor_err)626 __field(u32, vendor_err)
598 ),627 ),
599 628
600 TP_fast_assign(629 TP_fast_assign(
601 __entry->rep = rep;630 __entry->cqe = wc->wr_cqe;
602 __entry->byte_len = wc->byte_len;
603 __entry->status = wc->status;631 __entry->status = wc->status;
604 __entry->vendor_err = __entry->status ? wc->vendor_err : 0;632 if (wc->status) {
633 __entry->byte_len = 0;
634 __entry->vendor_err = wc->vendor_err;
635 } else {
636 __entry->byte_len = wc->byte_len;
637 __entry->vendor_err = 0;
638 }
605 ),639 ),
606 640
607 TP_printk("rep=%p, %u bytes: %s (%u/0x%x)",641 TP_printk("cqe=%p %u bytes: %s (%u/0x%x)",
608 __entry->rep, __entry->byte_len,642 __entry->cqe, __entry->byte_len,
609 rdma_show_wc_status(__entry->status),643 rdma_show_wc_status(__entry->status),
610 __entry->status, __entry->vendor_err644 __entry->status, __entry->vendor_err
611 )645 )
@@ -616,6 +650,7 @@ DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li); · 4 unmodified lines
616DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li_wake);650DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li_wake);
617 651
618DEFINE_MR_EVENT(xprtrdma_localinv);652DEFINE_MR_EVENT(xprtrdma_localinv);
653DEFINE_MR_EVENT(xprtrdma_dma_map);
619DEFINE_MR_EVENT(xprtrdma_dma_unmap);654DEFINE_MR_EVENT(xprtrdma_dma_unmap);
620DEFINE_MR_EVENT(xprtrdma_remoteinv);655DEFINE_MR_EVENT(xprtrdma_remoteinv);
621DEFINE_MR_EVENT(xprtrdma_recover_mr);656DEFINE_MR_EVENT(xprtrdma_recover_mr);
@@ -799,7 +834,6 @@ TRACE_EVENT(xprtrdma_allocate, · 177 unmodified lines
799 __field(unsigned int, task_id)834 __field(unsigned int, task_id)
800 __field(unsigned int, client_id)835 __field(unsigned int, client_id)
801 __field(const void *, req)836 __field(const void *, req)
802 __field(const void *, rep)
803 __field(size_t, callsize)837 __field(size_t, callsize)
804 __field(size_t, rcvsize)838 __field(size_t, rcvsize)
805 ),839 ),
@@ -808,15 +842,13 @@ TRACE_EVENT(xprtrdma_allocate, · 2 unmodified lines
808 __entry->task_id = task->tk_pid;842 __entry->task_id = task->tk_pid;
809 __entry->client_id = task->tk_client->cl_clid;843 __entry->client_id = task->tk_client->cl_clid;
810 __entry->req = req;844 __entry->req = req;
811 __entry->rep = req ? req->rl_reply : NULL;
812 __entry->callsize = task->tk_rqstp->rq_callsize;845 __entry->callsize = task->tk_rqstp->rq_callsize;
813 __entry->rcvsize = task->tk_rqstp->rq_rcvsize;846 __entry->rcvsize = task->tk_rqstp->rq_rcvsize;
814 ),847 ),
815 848
816 TP_printk("task:%u@%u req=%p rep=%p (%zu, %zu)",849 TP_printk("task:%u@%u req=%p (%zu, %zu)",
817 __entry->task_id, __entry->client_id,850 __entry->task_id, __entry->client_id,
818 __entry->req, __entry->rep,851 __entry->req, __entry->callsize, __entry->rcvsize
819 __entry->callsize, __entry->rcvsize
820 )852 )
821);853);
822 854
@@ -848,8 +880,6 @@ TRACE_EVENT(xprtrdma_rpc_done, · 25 unmodified lines
848 )880 )
849);881);
850 882
851DEFINE_RXPRT_EVENT(xprtrdma_noreps);
852
853/**883/**
854 ** Callback events884 ** Callback events
855 **/885 **/
net/sunrpc/clnt.c+1−0
@@ -1546,6 +1546,7 @@ call_reserveresult(struct rpc_task *task) · 1545 unmodified lines
1546 task->tk_status = 0;1546 task->tk_status = 0;
1547 if (status >= 0) {1547 if (status >= 0) {
1548 if (task->tk_rqstp) {1548 if (task->tk_rqstp) {
1549 xprt_request_init(task);
1549 task->tk_action = call_refresh;1550 task->tk_action = call_refresh;
1550 return;1551 return;
1551 }1552 }
net/sunrpc/xprt.c+10−7
@@ -66,7 +66,7 @@ · 65 unmodified lines
66 * Local functions66 * Local functions
67 */67 */
68static void xprt_init(struct rpc_xprt *xprt, struct net *net);68static void xprt_init(struct rpc_xprt *xprt, struct net *net);
69static void xprt_request_init(struct rpc_task *, struct rpc_xprt *);69static __be32 xprt_alloc_xid(struct rpc_xprt *xprt);
70static void xprt_connect_status(struct rpc_task *task);70static void xprt_connect_status(struct rpc_task *task);
71static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);71static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
72static void __xprt_put_cong(struct rpc_xprt *, struct rpc_rqst *);72static void __xprt_put_cong(struct rpc_xprt *, struct rpc_rqst *);
@@ -987,6 +987,8 @@ bool xprt_prepare_transmit(struct rpc_task *task) · 914 unmodified lines
987 task->tk_status = -EAGAIN;987 task->tk_status = -EAGAIN;
988 goto out_unlock;988 goto out_unlock;
989 }989 }
990 if (!bc_prealloc(req) && !req->rq_xmit_bytes_sent)
991 req->rq_xid = xprt_alloc_xid(xprt);
990 ret = true;992 ret = true;
991out_unlock:993out_unlock:
992 spin_unlock_bh(&xprt->transport_lock);994 spin_unlock_bh(&xprt->transport_lock);
@@ -1163,10 +1165,10 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) · 170 unmodified lines
1163out_init_req:1165out_init_req:
1164 xprt->stat.max_slots = max_t(unsigned int, xprt->stat.max_slots,1166 xprt->stat.max_slots = max_t(unsigned int, xprt->stat.max_slots,
1165 xprt->num_reqs);1167 xprt->num_reqs);
1168 spin_unlock(&xprt->reserve_lock);
1169
1166 task->tk_status = 0;1170 task->tk_status = 0;
1167 task->tk_rqstp = req;1171 task->tk_rqstp = req;
1168 xprt_request_init(task, xprt);
1169 spin_unlock(&xprt->reserve_lock);
1170}1172}
1171EXPORT_SYMBOL_GPL(xprt_alloc_slot);1173EXPORT_SYMBOL_GPL(xprt_alloc_slot);
1172 1174
@@ -1184,7 +1186,7 @@ void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) · 11 unmodified lines
1184}1186}
1185EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);1187EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);
1186 1188
1187static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)1189void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
1188{1190{
1189 spin_lock(&xprt->reserve_lock);1191 spin_lock(&xprt->reserve_lock);
1190 if (!xprt_dynamic_free_slot(xprt, req)) {1192 if (!xprt_dynamic_free_slot(xprt, req)) {
@@ -1194,6 +1196,7 @@ static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) · 3 unmodified lines
1194 xprt_wake_up_backlog(xprt);1196 xprt_wake_up_backlog(xprt);
1195 spin_unlock(&xprt->reserve_lock);1197 spin_unlock(&xprt->reserve_lock);
1196}1198}
1199EXPORT_SYMBOL_GPL(xprt_free_slot);
1197 1200
1198static void xprt_free_all_slots(struct rpc_xprt *xprt)1201static void xprt_free_all_slots(struct rpc_xprt *xprt)
1199{1202{
@@ -1303,8 +1306,9 @@ static inline void xprt_init_xid(struct rpc_xprt *xprt) · 103 unmodified lines
1303 xprt->xid = prandom_u32();1306 xprt->xid = prandom_u32();
1304}1307}
1305 1308
1306static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)1309void xprt_request_init(struct rpc_task *task)
1307{1310{
1311 struct rpc_xprt *xprt = task->tk_xprt;
1308 struct rpc_rqst *req = task->tk_rqstp;1312 struct rpc_rqst *req = task->tk_rqstp;
1309 1313
1310 INIT_LIST_HEAD(&req->rq_list);1314 INIT_LIST_HEAD(&req->rq_list);
@@ -1312,7 +1316,6 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) · 1 unmodified line
1312 req->rq_task = task;1316 req->rq_task = task;
1313 req->rq_xprt = xprt;1317 req->rq_xprt = xprt;
1314 req->rq_buffer = NULL;1318 req->rq_buffer = NULL;
1315 req->rq_xid = xprt_alloc_xid(xprt);
1316 req->rq_connect_cookie = xprt->connect_cookie - 1;1319 req->rq_connect_cookie = xprt->connect_cookie - 1;
1317 req->rq_bytes_sent = 0;1320 req->rq_bytes_sent = 0;
1318 req->rq_snd_buf.len = 0;1321 req->rq_snd_buf.len = 0;
@@ -1373,7 +1376,7 @@ void xprt_release(struct rpc_task *task) · 54 unmodified lines
1373 1376
1374 dprintk("RPC: %5u release request %p\n", task->tk_pid, req);1377 dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
1375 if (likely(!bc_prealloc(req)))1378 if (likely(!bc_prealloc(req)))
1376 xprt_free_slot(xprt, req);1379 xprt->ops->free_slot(xprt, req);
1377 else1380 else
1378 xprt_free_bc_request(req);1381 xprt_free_bc_request(req);
1379}1382}
net/sunrpc/xprtrdma/backchannel.c+39−66
@@ -29,29 +29,41 @@ static void rpcrdma_bc_free_rqst(struct rpcrdma_xprt *r_xprt, · 28 unmodified lines
29 spin_unlock(&buf->rb_reqslock);29 spin_unlock(&buf->rb_reqslock);
30 30
31 rpcrdma_destroy_req(req);31 rpcrdma_destroy_req(req);
32
33 kfree(rqst);
34}32}
35 33
36static int rpcrdma_bc_setup_rqst(struct rpcrdma_xprt *r_xprt,34static int rpcrdma_bc_setup_reqs(struct rpcrdma_xprt *r_xprt,
37 struct rpc_rqst *rqst)35 unsigned int count)
38{36{
39 struct rpcrdma_regbuf *rb;37 struct rpc_xprt *xprt = &r_xprt->rx_xprt;
40 struct rpcrdma_req *req;38 struct rpc_rqst *rqst;
41 size_t size;39 unsigned int i;
40
41 for (i = 0; i < (count << 1); i++) {
42 struct rpcrdma_regbuf *rb;
43 struct rpcrdma_req *req;
44 size_t size;
45
46 req = rpcrdma_create_req(r_xprt);
47 if (IS_ERR(req))
48 return PTR_ERR(req);
49 rqst = &req->rl_slot;
50
51 rqst->rq_xprt = xprt;
52 INIT_LIST_HEAD(&rqst->rq_list);
53 INIT_LIST_HEAD(&rqst->rq_bc_list);
54 __set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
55 spin_lock_bh(&xprt->bc_pa_lock);
56 list_add(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
57 spin_unlock_bh(&xprt->bc_pa_lock);
42 58
43 req = rpcrdma_create_req(r_xprt);59 size = r_xprt->rx_data.inline_rsize;
44 if (IS_ERR(req))60 rb = rpcrdma_alloc_regbuf(size, DMA_TO_DEVICE, GFP_KERNEL);
45 return PTR_ERR(req);61 if (IS_ERR(rb))
46 62 goto out_fail;
47 size = r_xprt->rx_data.inline_rsize;63 req->rl_sendbuf = rb;
48 rb = rpcrdma_alloc_regbuf(size, DMA_TO_DEVICE, GFP_KERNEL);64 xdr_buf_init(&rqst->rq_snd_buf, rb->rg_base,
49 if (IS_ERR(rb))65 min_t(size_t, size, PAGE_SIZE));
50 goto out_fail;66 }
51 req->rl_sendbuf = rb;
52 xdr_buf_init(&rqst->rq_snd_buf, rb->rg_base,
53 min_t(size_t, size, PAGE_SIZE));
54 rpcrdma_set_xprtdata(rqst, req);
55 return 0;67 return 0;
56 68
57out_fail:69out_fail:
@@ -59,23 +71,6 @@ out_fail: · 1 unmodified line
59 return -ENOMEM;71 return -ENOMEM;
60}72}
61 73
62/* Allocate and add receive buffers to the rpcrdma_buffer's
63 * existing list of rep's. These are released when the
64 * transport is destroyed.
65 */
66static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt,
67 unsigned int count)
68{
69 int rc = 0;
70
71 while (count--) {
72 rc = rpcrdma_create_rep(r_xprt);
73 if (rc)
74 break;
75 }
76 return rc;
77}
78
79/**74/**
80 * xprt_rdma_bc_setup - Pre-allocate resources for handling backchannel requests75 * xprt_rdma_bc_setup - Pre-allocate resources for handling backchannel requests
81 * @xprt: transport associated with these backchannel resources76 * @xprt: transport associated with these backchannel resources
@@ -86,9 +81,6 @@ static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt, · 4 unmodified lines
86int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)81int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)
87{82{
88 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);83 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
89 struct rpcrdma_buffer *buffer = &r_xprt->rx_buf;
90 struct rpc_rqst *rqst;
91 unsigned int i;
92 int rc;84 int rc;
93 85
94 /* The backchannel reply path returns each rpc_rqst to the86 /* The backchannel reply path returns each rpc_rqst to the
@@ -103,35 +95,11 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs) · 8 unmodified lines
103 if (reqs > RPCRDMA_BACKWARD_WRS >> 1)95 if (reqs > RPCRDMA_BACKWARD_WRS >> 1)
104 goto out_err;96 goto out_err;
105 97
106 for (i = 0; i < (reqs << 1); i++) {98 rc = rpcrdma_bc_setup_reqs(r_xprt, reqs);
107 rqst = kzalloc(sizeof(*rqst), GFP_KERNEL);
108 if (!rqst)
109 goto out_free;
110
111 dprintk("RPC: %s: new rqst %p\n", __func__, rqst);
112
113 rqst->rq_xprt = &r_xprt->rx_xprt;
114 INIT_LIST_HEAD(&rqst->rq_list);
115 INIT_LIST_HEAD(&rqst->rq_bc_list);
116 __set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
117
118 if (rpcrdma_bc_setup_rqst(r_xprt, rqst))
119 goto out_free;
120
121 spin_lock_bh(&xprt->bc_pa_lock);
122 list_add(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
123 spin_unlock_bh(&xprt->bc_pa_lock);
124 }
125
126 rc = rpcrdma_bc_setup_reps(r_xprt, reqs);
127 if (rc)99 if (rc)
128 goto out_free;100 goto out_free;
129 101
130 rc = rpcrdma_ep_post_extra_recv(r_xprt, reqs);102 r_xprt->rx_buf.rb_bc_srv_max_requests = reqs;
131 if (rc)
132 goto out_free;
133
134 buffer->rb_bc_srv_max_requests = reqs;
135 request_module("svcrdma");103 request_module("svcrdma");
136 trace_xprtrdma_cb_setup(r_xprt, reqs);104 trace_xprtrdma_cb_setup(r_xprt, reqs);
137 return 0;105 return 0;
@@ -235,6 +203,7 @@ int xprt_rdma_bc_send_reply(struct rpc_rqst *rqst) · 97 unmodified lines
235 if (rc < 0)203 if (rc < 0)
236 goto failed_marshal;204 goto failed_marshal;
237 205
206 rpcrdma_post_recvs(r_xprt, true);
238 if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req))207 if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req))
239 goto drop_connection;208 goto drop_connection;
240 return 0;209 return 0;
@@ -275,10 +244,14 @@ void xprt_rdma_bc_destroy(struct rpc_xprt *xprt, unsigned int reqs) · 34 unmodified lines
275 */244 */
276void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)245void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)
277{246{
247 struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
278 struct rpc_xprt *xprt = rqst->rq_xprt;248 struct rpc_xprt *xprt = rqst->rq_xprt;
279 249
280 dprintk("RPC: %s: freeing rqst %p (req %p)\n",250 dprintk("RPC: %s: freeing rqst %p (req %p)\n",
281 __func__, rqst, rpcr_to_rdmar(rqst));251 __func__, rqst, req);
252
253 rpcrdma_recv_buffer_put(req->rl_reply);
254 req->rl_reply = NULL;
282 255
283 spin_lock_bh(&xprt->bc_pa_lock);256 spin_lock_bh(&xprt->bc_pa_lock);
284 list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);257 list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
net/sunrpc/xprtrdma/fmr_ops.c+23−0
@@ -156,10 +156,32 @@ out_release: · 155 unmodified lines
156 fmr_op_release_mr(mr);156 fmr_op_release_mr(mr);
157}157}
158 158
159/* On success, sets:
160 * ep->rep_attr.cap.max_send_wr
161 * ep->rep_attr.cap.max_recv_wr
162 * cdata->max_requests
163 * ia->ri_max_segs
164 */
159static int165static int
160fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,166fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
161 struct rpcrdma_create_data_internal *cdata)167 struct rpcrdma_create_data_internal *cdata)
162{168{
169 int max_qp_wr;
170
171 max_qp_wr = ia->ri_device->attrs.max_qp_wr;
172 max_qp_wr -= RPCRDMA_BACKWARD_WRS;
173 max_qp_wr -= 1;
174 if (max_qp_wr < RPCRDMA_MIN_SLOT_TABLE)
175 return -ENOMEM;
176 if (cdata->max_requests > max_qp_wr)
177 cdata->max_requests = max_qp_wr;
178 ep->rep_attr.cap.max_send_wr = cdata->max_requests;
179 ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
180 ep->rep_attr.cap.max_send_wr += 1; /* for ib_drain_sq */
181 ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
182 ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
183 ep->rep_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
184
163 ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /185 ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
164 RPCRDMA_MAX_FMR_SGES);186 RPCRDMA_MAX_FMR_SGES);
165 return 0;187 return 0;
@@ -219,6 +241,7 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 53 unmodified lines
219 mr->mr_sg, i, mr->mr_dir);241 mr->mr_sg, i, mr->mr_dir);
220 if (!mr->mr_nents)242 if (!mr->mr_nents)
221 goto out_dmamap_err;243 goto out_dmamap_err;
244 trace_xprtrdma_dma_map(mr);
222 245
223 for (i = 0, dma_pages = mr->fmr.fm_physaddrs; i < mr->mr_nents; i++)246 for (i = 0, dma_pages = mr->fmr.fm_physaddrs; i < mr->mr_nents; i++)
224 dma_pages[i] = sg_dma_address(&mr->mr_sg[i]);247 dma_pages[i] = sg_dma_address(&mr->mr_sg[i]);
net/sunrpc/xprtrdma/frwr_ops.c+27−4
@@ -202,12 +202,22 @@ out_release: · 201 unmodified lines
202 frwr_op_release_mr(mr);202 frwr_op_release_mr(mr);
203}203}
204 204
205/* On success, sets:
206 * ep->rep_attr.cap.max_send_wr
207 * ep->rep_attr.cap.max_recv_wr
208 * cdata->max_requests
209 * ia->ri_max_segs
210 *
211 * And these FRWR-related fields:
212 * ia->ri_max_frwr_depth
213 * ia->ri_mrtype
214 */
205static int215static int
206frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,216frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
207 struct rpcrdma_create_data_internal *cdata)217 struct rpcrdma_create_data_internal *cdata)
208{218{
209 struct ib_device_attr *attrs = &ia->ri_device->attrs;219 struct ib_device_attr *attrs = &ia->ri_device->attrs;
210 int depth, delta;220 int max_qp_wr, depth, delta;
211 221
212 ia->ri_mrtype = IB_MR_TYPE_MEM_REG;222 ia->ri_mrtype = IB_MR_TYPE_MEM_REG;
213 if (attrs->device_cap_flags & IB_DEVICE_SG_GAPS_REG)223 if (attrs->device_cap_flags & IB_DEVICE_SG_GAPS_REG)
@@ -241,14 +251,26 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, · 27 unmodified lines
241 } while (delta > 0);251 } while (delta > 0);
242 }252 }
243 253
244 ep->rep_attr.cap.max_send_wr *= depth;254 max_qp_wr = ia->ri_device->attrs.max_qp_wr;
245 if (ep->rep_attr.cap.max_send_wr > attrs->max_qp_wr) {255 max_qp_wr -= RPCRDMA_BACKWARD_WRS;
246 cdata->max_requests = attrs->max_qp_wr / depth;256 max_qp_wr -= 1;
257 if (max_qp_wr < RPCRDMA_MIN_SLOT_TABLE)
258 return -ENOMEM;
259 if (cdata->max_requests > max_qp_wr)
260 cdata->max_requests = max_qp_wr;
261 ep->rep_attr.cap.max_send_wr = cdata->max_requests * depth;
262 if (ep->rep_attr.cap.max_send_wr > max_qp_wr) {
263 cdata->max_requests = max_qp_wr / depth;
247 if (!cdata->max_requests)264 if (!cdata->max_requests)
248 return -EINVAL;265 return -EINVAL;
249 ep->rep_attr.cap.max_send_wr = cdata->max_requests *266 ep->rep_attr.cap.max_send_wr = cdata->max_requests *
250 depth;267 depth;
251 }268 }
269 ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
270 ep->rep_attr.cap.max_send_wr += 1; /* for ib_drain_sq */
271 ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
272 ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
273 ep->rep_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
252 274
253 ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /275 ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
254 ia->ri_max_frwr_depth);276 ia->ri_max_frwr_depth);
@@ -393,6 +415,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, · 138 unmodified lines
393 mr->mr_nents = ib_dma_map_sg(ia->ri_device, mr->mr_sg, i, mr->mr_dir);415 mr->mr_nents = ib_dma_map_sg(ia->ri_device, mr->mr_sg, i, mr->mr_dir);
394 if (!mr->mr_nents)416 if (!mr->mr_nents)
395 goto out_dmamap_err;417 goto out_dmamap_err;
418 trace_xprtrdma_dma_map(mr);
396 419
397 ibmr = frwr->fr_mr;420 ibmr = frwr->fr_mr;
398 n = ib_map_mr_sg(ibmr, mr->mr_sg, mr->mr_nents, NULL, PAGE_SIZE);421 n = ib_map_mr_sg(ibmr, mr->mr_sg, mr->mr_nents, NULL, PAGE_SIZE);
net/sunrpc/xprtrdma/module.c+1−0
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
1/*2/*
2 * Copyright (c) 2015, 2017 Oracle. All rights reserved.3 * Copyright (c) 2015, 2017 Oracle. All rights reserved.
3 */4 */
net/sunrpc/xprtrdma/rpc_rdma.c+22−44
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
1/*2/*
2 * Copyright (c) 2014-2017 Oracle. All rights reserved.3 * Copyright (c) 2014-2017 Oracle. All rights reserved.
3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.4 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -54,14 +55,6 @@ · 50 unmodified lines
54# define RPCDBG_FACILITY RPCDBG_TRANS55# define RPCDBG_FACILITY RPCDBG_TRANS
55#endif56#endif
56 57
57static const char transfertypes[][12] = {
58 "inline", /* no chunks */
59 "read list", /* some argument via rdma read */
60 "*read list", /* entire request via rdma read */
61 "write list", /* some result via rdma write */
62 "reply chunk" /* entire reply via rdma write */
63};
64
65/* Returns size of largest RPC-over-RDMA header in a Call message58/* Returns size of largest RPC-over-RDMA header in a Call message
66 *59 *
67 * The largest Call header contains a full-size Read list and a60 * The largest Call header contains a full-size Read list and a
@@ -230,7 +223,7 @@ rpcrdma_convert_iovs(struct rpcrdma_xprt *r_xprt, struct xdr_buf *xdrbuf, · 162 unmodified lines
230 */223 */
231 *ppages = alloc_page(GFP_ATOMIC);224 *ppages = alloc_page(GFP_ATOMIC);
232 if (!*ppages)225 if (!*ppages)
233 return -EAGAIN;226 return -ENOBUFS;
234 }227 }
235 seg->mr_page = *ppages;228 seg->mr_page = *ppages;
236 seg->mr_offset = (char *)page_base;229 seg->mr_offset = (char *)page_base;
@@ -365,7 +358,7 @@ rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, · 128 unmodified lines
365 seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,358 seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,
366 false, &mr);359 false, &mr);
367 if (IS_ERR(seg))360 if (IS_ERR(seg))
368 goto out_maperr;361 return PTR_ERR(seg);
369 rpcrdma_mr_push(mr, &req->rl_registered);362 rpcrdma_mr_push(mr, &req->rl_registered);
370 363
371 if (encode_read_segment(xdr, mr, pos) < 0)364 if (encode_read_segment(xdr, mr, pos) < 0)
@@ -377,11 +370,6 @@ rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, · 5 unmodified lines
377 } while (nsegs);370 } while (nsegs);
378 371
379 return 0;372 return 0;
380
381out_maperr:
382 if (PTR_ERR(seg) == -EAGAIN)
383 xprt_wait_for_buffer_space(rqst->rq_task, NULL);
384 return PTR_ERR(seg);
385}373}
386 374
387/* Register and XDR encode the Write list. Supports encoding a list375/* Register and XDR encode the Write list. Supports encoding a list
@@ -428,7 +416,7 @@ rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, · 40 unmodified lines
428 seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,416 seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,
429 true, &mr);417 true, &mr);
430 if (IS_ERR(seg))418 if (IS_ERR(seg))
431 goto out_maperr;419 return PTR_ERR(seg);
432 rpcrdma_mr_push(mr, &req->rl_registered);420 rpcrdma_mr_push(mr, &req->rl_registered);
433 421
434 if (encode_rdma_segment(xdr, mr) < 0)422 if (encode_rdma_segment(xdr, mr) < 0)
@@ -445,11 +433,6 @@ rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, · 10 unmodified lines
445 *segcount = cpu_to_be32(nchunks);433 *segcount = cpu_to_be32(nchunks);
446 434
447 return 0;435 return 0;
448
449out_maperr:
450 if (PTR_ERR(seg) == -EAGAIN)
451 xprt_wait_for_buffer_space(rqst->rq_task, NULL);
452 return PTR_ERR(seg);
453}436}
454 437
455/* Register and XDR encode the Reply chunk. Supports encoding an array438/* Register and XDR encode the Reply chunk. Supports encoding an array
@@ -491,7 +474,7 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, · 35 unmodified lines
491 seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,474 seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,
492 true, &mr);475 true, &mr);
493 if (IS_ERR(seg))476 if (IS_ERR(seg))
494 goto out_maperr;477 return PTR_ERR(seg);
495 rpcrdma_mr_push(mr, &req->rl_registered);478 rpcrdma_mr_push(mr, &req->rl_registered);
496 479
497 if (encode_rdma_segment(xdr, mr) < 0)480 if (encode_rdma_segment(xdr, mr) < 0)
@@ -508,11 +491,6 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, · 10 unmodified lines
508 *segcount = cpu_to_be32(nchunks);491 *segcount = cpu_to_be32(nchunks);
509 492
510 return 0;493 return 0;
511
512out_maperr:
513 if (PTR_ERR(seg) == -EAGAIN)
514 xprt_wait_for_buffer_space(rqst->rq_task, NULL);
515 return PTR_ERR(seg);
516}494}
517 495
518/**496/**
@@ -709,7 +687,7 @@ rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt, · 190 unmodified lines
709{687{
710 req->rl_sendctx = rpcrdma_sendctx_get_locked(&r_xprt->rx_buf);688 req->rl_sendctx = rpcrdma_sendctx_get_locked(&r_xprt->rx_buf);
711 if (!req->rl_sendctx)689 if (!req->rl_sendctx)
712 return -ENOBUFS;690 return -EAGAIN;
713 req->rl_sendctx->sc_wr.num_sge = 0;691 req->rl_sendctx->sc_wr.num_sge = 0;
714 req->rl_sendctx->sc_unmap_count = 0;692 req->rl_sendctx->sc_unmap_count = 0;
715 req->rl_sendctx->sc_req = req;693 req->rl_sendctx->sc_req = req;
@@ -883,7 +861,15 @@ rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst) · 167 unmodified lines
883 return 0;861 return 0;
884 862
885out_err:863out_err:
886 r_xprt->rx_stats.failed_marshal_count++;864 switch (ret) {
865 case -EAGAIN:
866 xprt_wait_for_buffer_space(rqst->rq_task, NULL);
867 break;
868 case -ENOBUFS:
869 break;
870 default:
871 r_xprt->rx_stats.failed_marshal_count++;
872 }
887 return ret;873 return ret;
888}874}
889 875
@@ -1026,8 +1012,6 @@ rpcrdma_is_bcall(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep) · 136 unmodified lines
1026 1012
1027out_short:1013out_short:
1028 pr_warn("RPC/RDMA short backward direction call\n");1014 pr_warn("RPC/RDMA short backward direction call\n");
1029 if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep))
1030 xprt_disconnect_done(&r_xprt->rx_xprt);
1031 return true;1015 return true;
1032}1016}
1033#else /* CONFIG_SUNRPC_BACKCHANNEL */1017#else /* CONFIG_SUNRPC_BACKCHANNEL */
@@ -1333,13 +1317,14 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) · 299 unmodified lines
1333 u32 credits;1317 u32 credits;
1334 __be32 *p;1318 __be32 *p;
1335 1319
1320 --buf->rb_posted_receives;
1321
1336 if (rep->rr_hdrbuf.head[0].iov_len == 0)1322 if (rep->rr_hdrbuf.head[0].iov_len == 0)
1337 goto out_badstatus;1323 goto out_badstatus;
1338 1324
1325 /* Fixed transport header fields */
1339 xdr_init_decode(&rep->rr_stream, &rep->rr_hdrbuf,1326 xdr_init_decode(&rep->rr_stream, &rep->rr_hdrbuf,
1340 rep->rr_hdrbuf.head[0].iov_base);1327 rep->rr_hdrbuf.head[0].iov_base);
1341
1342 /* Fixed transport header fields */
1343 p = xdr_inline_decode(&rep->rr_stream, 4 * sizeof(*p));1328 p = xdr_inline_decode(&rep->rr_stream, 4 * sizeof(*p));
1344 if (unlikely(!p))1329 if (unlikely(!p))
1345 goto out_shortreply;1330 goto out_shortreply;
@@ -1378,17 +1363,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) · 32 unmodified lines
1378 1363
1379 trace_xprtrdma_reply(rqst->rq_task, rep, req, credits);1364 trace_xprtrdma_reply(rqst->rq_task, rep, req, credits);
1380 1365
1366 rpcrdma_post_recvs(r_xprt, false);
1381 queue_work(rpcrdma_receive_wq, &rep->rr_work);1367 queue_work(rpcrdma_receive_wq, &rep->rr_work);
1382 return;1368 return;
1383 1369
1384out_badstatus:
1385 rpcrdma_recv_buffer_put(rep);
1386 if (r_xprt->rx_ep.rep_connected == 1) {
1387 r_xprt->rx_ep.rep_connected = -EIO;
1388 rpcrdma_conn_func(&r_xprt->rx_ep);
1389 }
1390 return;
1391
1392out_badversion:1370out_badversion:
1393 trace_xprtrdma_reply_vers(rep);1371 trace_xprtrdma_reply_vers(rep);
1394 goto repost;1372 goto repost;
@@ -1408,7 +1386,7 @@ out_shortreply: · 13 unmodified lines
1408 * receive buffer before returning.1386 * receive buffer before returning.
1409 */1387 */
1410repost:1388repost:
1411 r_xprt->rx_stats.bad_reply_count++;1389 rpcrdma_post_recvs(r_xprt, false);
1412 if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep))1390out_badstatus:
1413 rpcrdma_recv_buffer_put(rep);1391 rpcrdma_recv_buffer_put(rep);
1414}1392}
net/sunrpc/xprtrdma/svc_rdma_backchannel.c+1−0
@@ -273,6 +273,7 @@ static const struct rpc_xprt_ops xprt_rdma_bc_procs = { · 272 unmodified lines
273 .reserve_xprt = xprt_reserve_xprt_cong,273 .reserve_xprt = xprt_reserve_xprt_cong,
274 .release_xprt = xprt_release_xprt_cong,274 .release_xprt = xprt_release_xprt_cong,
275 .alloc_slot = xprt_alloc_slot,275 .alloc_slot = xprt_alloc_slot,
276 .free_slot = xprt_free_slot,
276 .release_request = xprt_release_rqst_cong,277 .release_request = xprt_release_rqst_cong,
277 .buf_alloc = xprt_rdma_bc_allocate,278 .buf_alloc = xprt_rdma_bc_allocate,
278 .buf_free = xprt_rdma_bc_free,279 .buf_free = xprt_rdma_bc_free,
net/sunrpc/xprtrdma/transport.c+47−17
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
1/*2/*
2 * Copyright (c) 2014-2017 Oracle. All rights reserved.3 * Copyright (c) 2014-2017 Oracle. All rights reserved.
3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.4 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -330,9 +331,7 @@ xprt_setup_rdma(struct xprt_create *args) · 326 unmodified lines
330 return ERR_PTR(-EBADF);331 return ERR_PTR(-EBADF);
331 }332 }
332 333
333 xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt),334 xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt), 0, 0);
334 xprt_rdma_slot_table_entries,
335 xprt_rdma_slot_table_entries);
336 if (xprt == NULL) {335 if (xprt == NULL) {
337 dprintk("RPC: %s: couldn't allocate rpcrdma_xprt\n",336 dprintk("RPC: %s: couldn't allocate rpcrdma_xprt\n",
338 __func__);337 __func__);
@@ -364,7 +363,7 @@ xprt_setup_rdma(struct xprt_create *args) · 25 unmodified lines
364 xprt_set_bound(xprt);363 xprt_set_bound(xprt);
365 xprt_rdma_format_addresses(xprt, sap);364 xprt_rdma_format_addresses(xprt, sap);
366 365
367 cdata.max_requests = xprt->max_reqs;366 cdata.max_requests = xprt_rdma_slot_table_entries;
368 367
369 cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */368 cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */
370 cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */369 cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */
@@ -537,6 +536,47 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task) · 166 unmodified lines
537 }536 }
538}537}
539 538
539/**
540 * xprt_rdma_alloc_slot - allocate an rpc_rqst
541 * @xprt: controlling RPC transport
542 * @task: RPC task requesting a fresh rpc_rqst
543 *
544 * tk_status values:
545 * %0 if task->tk_rqstp points to a fresh rpc_rqst
546 * %-EAGAIN if no rpc_rqst is available; queued on backlog
547 */
548static void
549xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
550{
551 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
552 struct rpcrdma_req *req;
553
554 req = rpcrdma_buffer_get(&r_xprt->rx_buf);
555 if (!req)
556 goto out_sleep;
557 task->tk_rqstp = &req->rl_slot;
558 task->tk_status = 0;
559 return;
560
561out_sleep:
562 rpc_sleep_on(&xprt->backlog, task, NULL);
563 task->tk_status = -EAGAIN;
564}
565
566/**
567 * xprt_rdma_free_slot - release an rpc_rqst
568 * @xprt: controlling RPC transport
569 * @rqst: rpc_rqst to release
570 *
571 */
572static void
573xprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst)
574{
575 memset(rqst, 0, sizeof(*rqst));
576 rpcrdma_buffer_put(rpcr_to_rdmar(rqst));
577 rpc_wake_up_next(&xprt->backlog);
578}
579
540static bool580static bool
541rpcrdma_get_sendbuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,581rpcrdma_get_sendbuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
542 size_t size, gfp_t flags)582 size_t size, gfp_t flags)
@@ -607,13 +647,9 @@ xprt_rdma_allocate(struct rpc_task *task) · 64 unmodified lines
607{647{
608 struct rpc_rqst *rqst = task->tk_rqstp;648 struct rpc_rqst *rqst = task->tk_rqstp;
609 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);649 struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);
610 struct rpcrdma_req *req;650 struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
611 gfp_t flags;651 gfp_t flags;
612 652
613 req = rpcrdma_buffer_get(&r_xprt->rx_buf);
614 if (req == NULL)
615 goto out_get;
616
617 flags = RPCRDMA_DEF_GFP;653 flags = RPCRDMA_DEF_GFP;
618 if (RPC_IS_SWAPPER(task))654 if (RPC_IS_SWAPPER(task))
619 flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;655 flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
@@ -623,15 +659,12 @@ xprt_rdma_allocate(struct rpc_task *task) · 3 unmodified lines
623 if (!rpcrdma_get_recvbuf(r_xprt, req, rqst->rq_rcvsize, flags))659 if (!rpcrdma_get_recvbuf(r_xprt, req, rqst->rq_rcvsize, flags))
624 goto out_fail;660 goto out_fail;
625 661
626 rpcrdma_set_xprtdata(rqst, req);
627 rqst->rq_buffer = req->rl_sendbuf->rg_base;662 rqst->rq_buffer = req->rl_sendbuf->rg_base;
628 rqst->rq_rbuffer = req->rl_recvbuf->rg_base;663 rqst->rq_rbuffer = req->rl_recvbuf->rg_base;
629 trace_xprtrdma_allocate(task, req);664 trace_xprtrdma_allocate(task, req);
630 return 0;665 return 0;
631 666
632out_fail:667out_fail:
633 rpcrdma_buffer_put(req);
634out_get:
635 trace_xprtrdma_allocate(task, NULL);668 trace_xprtrdma_allocate(task, NULL);
636 return -ENOMEM;669 return -ENOMEM;
637}670}
@@ -652,7 +685,6 @@ xprt_rdma_free(struct rpc_task *task) · 14 unmodified lines
652 if (test_bit(RPCRDMA_REQ_F_PENDING, &req->rl_flags))685 if (test_bit(RPCRDMA_REQ_F_PENDING, &req->rl_flags))
653 rpcrdma_release_rqst(r_xprt, req);686 rpcrdma_release_rqst(r_xprt, req);
654 trace_xprtrdma_rpc_done(task, req);687 trace_xprtrdma_rpc_done(task, req);
655 rpcrdma_buffer_put(req);
656}688}
657 689
658/**690/**
@@ -690,9 +722,6 @@ xprt_rdma_send_request(struct rpc_task *task) · 31 unmodified lines
690 if (rc < 0)722 if (rc < 0)
691 goto failed_marshal;723 goto failed_marshal;
692 724
693 if (req->rl_reply == NULL) /* e.g. reconnection */
694 rpcrdma_recv_buffer_get(req);
695
696 /* Must suppress retransmit to maintain credits */725 /* Must suppress retransmit to maintain credits */
697 if (rqst->rq_connect_cookie == xprt->connect_cookie)726 if (rqst->rq_connect_cookie == xprt->connect_cookie)
698 goto drop_connection;727 goto drop_connection;
@@ -779,7 +808,8 @@ xprt_rdma_disable_swap(struct rpc_xprt *xprt) · 80 unmodified lines
779static const struct rpc_xprt_ops xprt_rdma_procs = {808static const struct rpc_xprt_ops xprt_rdma_procs = {
780 .reserve_xprt = xprt_reserve_xprt_cong,809 .reserve_xprt = xprt_reserve_xprt_cong,
781 .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */810 .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */
782 .alloc_slot = xprt_alloc_slot,811 .alloc_slot = xprt_rdma_alloc_slot,
812 .free_slot = xprt_rdma_free_slot,
783 .release_request = xprt_release_rqst_cong, /* ditto */813 .release_request = xprt_release_rqst_cong, /* ditto */
784 .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */814 .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */
785 .timer = xprt_rdma_timer,815 .timer = xprt_rdma_timer,
net/sunrpc/xprtrdma/verbs.c+112−179
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
1/*2/*
2 * Copyright (c) 2014-2017 Oracle. All rights reserved.3 * Copyright (c) 2014-2017 Oracle. All rights reserved.
3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.4 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -71,8 +72,10 @@ · 67 unmodified lines
71/*72/*
72 * internal functions73 * internal functions
73 */74 */
75static void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc);
74static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);76static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
75static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);77static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);
78static int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp);
76static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb);79static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb);
77 80
78struct workqueue_struct *rpcrdma_receive_wq __read_mostly;81struct workqueue_struct *rpcrdma_receive_wq __read_mostly;
@@ -159,7 +162,7 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) · 80 unmodified lines
159 rr_cqe);162 rr_cqe);
160 163
161 /* WARNING: Only wr_id and status are reliable at this point */164 /* WARNING: Only wr_id and status are reliable at this point */
162 trace_xprtrdma_wc_receive(rep, wc);165 trace_xprtrdma_wc_receive(wc);
163 if (wc->status != IB_WC_SUCCESS)166 if (wc->status != IB_WC_SUCCESS)
164 goto out_fail;167 goto out_fail;
165 168
@@ -231,7 +234,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 65 unmodified lines
231 complete(&ia->ri_done);234 complete(&ia->ri_done);
232 break;235 break;
233 case RDMA_CM_EVENT_ADDR_ERROR:236 case RDMA_CM_EVENT_ADDR_ERROR:
234 ia->ri_async_rc = -EHOSTUNREACH;237 ia->ri_async_rc = -EPROTO;
235 complete(&ia->ri_done);238 complete(&ia->ri_done);
236 break;239 break;
237 case RDMA_CM_EVENT_ROUTE_ERROR:240 case RDMA_CM_EVENT_ROUTE_ERROR:
@@ -262,7 +265,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) · 24 unmodified lines
262 connstate = -ENOTCONN;265 connstate = -ENOTCONN;
263 goto connected;266 goto connected;
264 case RDMA_CM_EVENT_UNREACHABLE:267 case RDMA_CM_EVENT_UNREACHABLE:
265 connstate = -ENETDOWN;268 connstate = -ENETUNREACH;
266 goto connected;269 goto connected;
267 case RDMA_CM_EVENT_REJECTED:270 case RDMA_CM_EVENT_REJECTED:
268 dprintk("rpcrdma: connection to %s:%s rejected: %s\n",271 dprintk("rpcrdma: connection to %s:%s rejected: %s\n",
@@ -305,8 +308,8 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rpcrdma_ia *ia) · 36 unmodified lines
305 init_completion(&ia->ri_done);308 init_completion(&ia->ri_done);
306 init_completion(&ia->ri_remove_done);309 init_completion(&ia->ri_remove_done);
307 310
308 id = rdma_create_id(&init_net, rpcrdma_conn_upcall, xprt, RDMA_PS_TCP,311 id = rdma_create_id(xprt->rx_xprt.xprt_net, rpcrdma_conn_upcall,
309 IB_QPT_RC);312 xprt, RDMA_PS_TCP, IB_QPT_RC);
310 if (IS_ERR(id)) {313 if (IS_ERR(id)) {
311 rc = PTR_ERR(id);314 rc = PTR_ERR(id);
312 dprintk("RPC: %s: rdma_create_id() failed %i\n",315 dprintk("RPC: %s: rdma_create_id() failed %i\n",
@@ -500,8 +503,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, · 187 unmodified lines
500 struct rpcrdma_create_data_internal *cdata)503 struct rpcrdma_create_data_internal *cdata)
501{504{
502 struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;505 struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
503 unsigned int max_qp_wr, max_sge;
504 struct ib_cq *sendcq, *recvcq;506 struct ib_cq *sendcq, *recvcq;
507 unsigned int max_sge;
505 int rc;508 int rc;
506 509
507 max_sge = min_t(unsigned int, ia->ri_device->attrs.max_sge,510 max_sge = min_t(unsigned int, ia->ri_device->attrs.max_sge,
@@ -512,29 +515,13 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, · 4 unmodified lines
512 }515 }
513 ia->ri_max_send_sges = max_sge;516 ia->ri_max_send_sges = max_sge;
514 517
515 if (ia->ri_device->attrs.max_qp_wr <= RPCRDMA_BACKWARD_WRS) {518 rc = ia->ri_ops->ro_open(ia, ep, cdata);
516 dprintk("RPC: %s: insufficient wqe's available\n",519 if (rc)
517 __func__);520 return rc;
518 return -ENOMEM;
519 }
520 max_qp_wr = ia->ri_device->attrs.max_qp_wr - RPCRDMA_BACKWARD_WRS - 1;
521
522 /* check provider's send/recv wr limits */
523 if (cdata->max_requests > max_qp_wr)
524 cdata->max_requests = max_qp_wr;
525 521
526 ep->rep_attr.event_handler = rpcrdma_qp_async_error_upcall;522 ep->rep_attr.event_handler = rpcrdma_qp_async_error_upcall;
527 ep->rep_attr.qp_context = ep;523 ep->rep_attr.qp_context = ep;
528 ep->rep_attr.srq = NULL;524 ep->rep_attr.srq = NULL;
529 ep->rep_attr.cap.max_send_wr = cdata->max_requests;
530 ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
531 ep->rep_attr.cap.max_send_wr += 1; /* drain cqe */
532 rc = ia->ri_ops->ro_open(ia, ep, cdata);
533 if (rc)
534 return rc;
535 ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
536 ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
537 ep->rep_attr.cap.max_recv_wr += 1; /* drain cqe */
538 ep->rep_attr.cap.max_send_sge = max_sge;525 ep->rep_attr.cap.max_send_sge = max_sge;
539 ep->rep_attr.cap.max_recv_sge = 1;526 ep->rep_attr.cap.max_recv_sge = 1;
540 ep->rep_attr.cap.max_inline_data = 0;527 ep->rep_attr.cap.max_inline_data = 0;
@@ -741,7 +728,6 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) · 200 unmodified lines
741{728{
742 struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,729 struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
743 rx_ia);730 rx_ia);
744 unsigned int extras;
745 int rc;731 int rc;
746 732
747retry:733retry:
@@ -785,9 +771,8 @@ retry: · 37 unmodified lines
785 }771 }
786 772
787 dprintk("RPC: %s: connected\n", __func__);773 dprintk("RPC: %s: connected\n", __func__);
788 extras = r_xprt->rx_buf.rb_bc_srv_max_requests;774
789 if (extras)775 rpcrdma_post_recvs(r_xprt, true);
790 rpcrdma_ep_post_extra_recv(r_xprt, extras);
791 776
792out:777out:
793 if (rc)778 if (rc)
@@ -893,6 +878,7 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt) · 99 unmodified lines
893 sc->sc_xprt = r_xprt;878 sc->sc_xprt = r_xprt;
894 buf->rb_sc_ctxs[i] = sc;879 buf->rb_sc_ctxs[i] = sc;
895 }880 }
881 buf->rb_flags = 0;
896 882
897 return 0;883 return 0;
898 884
@@ -950,7 +936,7 @@ out_emptyq: · 51 unmodified lines
950 * completions recently. This is a sign the Send Queue is936 * completions recently. This is a sign the Send Queue is
951 * backing up. Cause the caller to pause and try again.937 * backing up. Cause the caller to pause and try again.
952 */938 */
953 dprintk("RPC: %s: empty sendctx queue\n", __func__);939 set_bit(RPCRDMA_BUF_F_EMPTY_SCQ, &buf->rb_flags);
954 r_xprt = container_of(buf, struct rpcrdma_xprt, rx_buf);940 r_xprt = container_of(buf, struct rpcrdma_xprt, rx_buf);
955 r_xprt->rx_stats.empty_sendctx_q++;941 r_xprt->rx_stats.empty_sendctx_q++;
956 return NULL;942 return NULL;
@@ -965,7 +951,8 @@ out_emptyq: · 8 unmodified lines
965 *951 *
966 * The caller serializes calls to this function (per rpcrdma_buffer).952 * The caller serializes calls to this function (per rpcrdma_buffer).
967 */953 */
968void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc)954static void
955rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc)
969{956{
970 struct rpcrdma_buffer *buf = &sc->sc_xprt->rx_buf;957 struct rpcrdma_buffer *buf = &sc->sc_xprt->rx_buf;
971 unsigned long next_tail;958 unsigned long next_tail;
@@ -984,6 +971,11 @@ void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc) · 12 unmodified lines
984 971
985 /* Paired with READ_ONCE */972 /* Paired with READ_ONCE */
986 smp_store_release(&buf->rb_sc_tail, next_tail);973 smp_store_release(&buf->rb_sc_tail, next_tail);
974
975 if (test_and_clear_bit(RPCRDMA_BUF_F_EMPTY_SCQ, &buf->rb_flags)) {
976 smp_mb__after_atomic();
977 xprt_write_space(&sc->sc_xprt->rx_xprt);
978 }
987}979}
988 980
989static void981static void
@@ -1097,14 +1089,8 @@ rpcrdma_create_req(struct rpcrdma_xprt *r_xprt) · 107 unmodified lines
1097 return req;1089 return req;
1098}1090}
1099 1091
1100/**1092static int
1101 * rpcrdma_create_rep - Allocate an rpcrdma_rep object1093rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp)
1102 * @r_xprt: controlling transport
1103 *
1104 * Returns 0 on success or a negative errno on failure.
1105 */
1106int
1107rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
1108{1094{
1109 struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;1095 struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
1110 struct rpcrdma_buffer *buf = &r_xprt->rx_buf;1096 struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
@@ -1132,6 +1118,7 @@ rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt) · 21 unmodified lines
1132 rep->rr_recv_wr.wr_cqe = &rep->rr_cqe;1118 rep->rr_recv_wr.wr_cqe = &rep->rr_cqe;
1133 rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;1119 rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
1134 rep->rr_recv_wr.num_sge = 1;1120 rep->rr_recv_wr.num_sge = 1;
1121 rep->rr_temp = temp;
1135 1122
1136 spin_lock(&buf->rb_lock);1123 spin_lock(&buf->rb_lock);
1137 list_add(&rep->rr_list, &buf->rb_recv_bufs);1124 list_add(&rep->rr_list, &buf->rb_recv_bufs);
@@ -1183,12 +1170,8 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt) · 45 unmodified lines
1183 list_add(&req->rl_list, &buf->rb_send_bufs);1170 list_add(&req->rl_list, &buf->rb_send_bufs);
1184 }1171 }
1185 1172
1173 buf->rb_posted_receives = 0;
1186 INIT_LIST_HEAD(&buf->rb_recv_bufs);1174 INIT_LIST_HEAD(&buf->rb_recv_bufs);
1187 for (i = 0; i <= buf->rb_max_requests; i++) {
1188 rc = rpcrdma_create_rep(r_xprt);
1189 if (rc)
1190 goto out;
1191 }
1192 1175
1193 rc = rpcrdma_sendctxs_create(r_xprt);1176 rc = rpcrdma_sendctxs_create(r_xprt);
1194 if (rc)1177 if (rc)
@@ -1200,28 +1183,6 @@ out: · 5 unmodified lines
1200 return rc;1183 return rc;
1201}1184}
1202 1185
1203static struct rpcrdma_req *
1204rpcrdma_buffer_get_req_locked(struct rpcrdma_buffer *buf)
1205{
1206 struct rpcrdma_req *req;
1207
1208 req = list_first_entry(&buf->rb_send_bufs,
1209 struct rpcrdma_req, rl_list);
1210 list_del_init(&req->rl_list);
1211 return req;
1212}
1213
1214static struct rpcrdma_rep *
1215rpcrdma_buffer_get_rep_locked(struct rpcrdma_buffer *buf)
1216{
1217 struct rpcrdma_rep *rep;
1218
1219 rep = list_first_entry(&buf->rb_recv_bufs,
1220 struct rpcrdma_rep, rr_list);
1221 list_del(&rep->rr_list);
1222 return rep;
1223}
1224
1225static void1186static void
1226rpcrdma_destroy_rep(struct rpcrdma_rep *rep)1187rpcrdma_destroy_rep(struct rpcrdma_rep *rep)
1227{1188{
@@ -1280,10 +1241,11 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) · 52 unmodified lines
1280 while (!list_empty(&buf->rb_recv_bufs)) {1241 while (!list_empty(&buf->rb_recv_bufs)) {
1281 struct rpcrdma_rep *rep;1242 struct rpcrdma_rep *rep;
1282 1243
1283 rep = rpcrdma_buffer_get_rep_locked(buf);1244 rep = list_first_entry(&buf->rb_recv_bufs,
1245 struct rpcrdma_rep, rr_list);
1246 list_del(&rep->rr_list);
1284 rpcrdma_destroy_rep(rep);1247 rpcrdma_destroy_rep(rep);
1285 }1248 }
1286 buf->rb_send_count = 0;
1287 1249
1288 spin_lock(&buf->rb_reqslock);1250 spin_lock(&buf->rb_reqslock);
1289 while (!list_empty(&buf->rb_allreqs)) {1251 while (!list_empty(&buf->rb_allreqs)) {
@@ -1298,7 +1260,6 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) · 8 unmodified lines
1298 spin_lock(&buf->rb_reqslock);1260 spin_lock(&buf->rb_reqslock);
1299 }1261 }
1300 spin_unlock(&buf->rb_reqslock);1262 spin_unlock(&buf->rb_reqslock);
1301 buf->rb_recv_count = 0;
1302 1263
1303 rpcrdma_mrs_destroy(buf);1264 rpcrdma_mrs_destroy(buf);
1304}1265}
@@ -1371,27 +1332,11 @@ rpcrdma_mr_unmap_and_put(struct rpcrdma_mr *mr) · 66 unmodified lines
1371 __rpcrdma_mr_put(&r_xprt->rx_buf, mr);1332 __rpcrdma_mr_put(&r_xprt->rx_buf, mr);
1372}1333}
1373 1334
1374static struct rpcrdma_rep *1335/**
1375rpcrdma_buffer_get_rep(struct rpcrdma_buffer *buffers)1336 * rpcrdma_buffer_get - Get a request buffer
1376{1337 * @buffers: Buffer pool from which to obtain a buffer
1377 /* If an RPC previously completed without a reply (say, a
1378 * credential problem or a soft timeout occurs) then hold off
1379 * on supplying more Receive buffers until the number of new
1380 * pending RPCs catches up to the number of posted Receives.
1381 */
1382 if (unlikely(buffers->rb_send_count < buffers->rb_recv_count))
1383 return NULL;
1384
1385 if (unlikely(list_empty(&buffers->rb_recv_bufs)))
1386 return NULL;
1387 buffers->rb_recv_count++;
1388 return rpcrdma_buffer_get_rep_locked(buffers);
1389}
1390
1391/*
1392 * Get a set of request/reply buffers.
1393 *1338 *
1394 * Reply buffer (if available) is attached to send buffer upon return.1339 * Returns a fresh rpcrdma_req, or NULL if none are available.
1395 */1340 */
1396struct rpcrdma_req *1341struct rpcrdma_req *
1397rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)1342rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
@@ -1399,23 +1344,18 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) · 1 unmodified line
1399 struct rpcrdma_req *req;1344 struct rpcrdma_req *req;
1400 1345
1401 spin_lock(&buffers->rb_lock);1346 spin_lock(&buffers->rb_lock);
1402 if (list_empty(&buffers->rb_send_bufs))1347 req = list_first_entry_or_null(&buffers->rb_send_bufs,
1403 goto out_reqbuf;1348 struct rpcrdma_req, rl_list);
1404 buffers->rb_send_count++;1349 if (req)
1405 req = rpcrdma_buffer_get_req_locked(buffers);1350 list_del_init(&req->rl_list);
1406 req->rl_reply = rpcrdma_buffer_get_rep(buffers);
1407 spin_unlock(&buffers->rb_lock);1351 spin_unlock(&buffers->rb_lock);
1408
1409 return req;1352 return req;
1410
1411out_reqbuf:
1412 spin_unlock(&buffers->rb_lock);
1413 return NULL;
1414}1353}
1415 1354
1416/*1355/**
1417 * Put request/reply buffers back into pool.1356 * rpcrdma_buffer_put - Put request/reply buffers back into pool
1418 * Pre-decrement counter/array index.1357 * @req: object to return
1358 *
1419 */1359 */
1420void1360void
1421rpcrdma_buffer_put(struct rpcrdma_req *req)1361rpcrdma_buffer_put(struct rpcrdma_req *req)
@@ -1426,27 +1366,16 @@ rpcrdma_buffer_put(struct rpcrdma_req *req) · 4 unmodified lines
1426 req->rl_reply = NULL;1366 req->rl_reply = NULL;
1427 1367
1428 spin_lock(&buffers->rb_lock);1368 spin_lock(&buffers->rb_lock);
1429 buffers->rb_send_count--;1369 list_add(&req->rl_list, &buffers->rb_send_bufs);
1430 list_add_tail(&req->rl_list, &buffers->rb_send_bufs);
1431 if (rep) {1370 if (rep) {
1432 buffers->rb_recv_count--;1371 if (!rep->rr_temp) {
1433 list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs);1372 list_add(&rep->rr_list, &buffers->rb_recv_bufs);
1373 rep = NULL;
1374 }
1434 }1375 }
1435 spin_unlock(&buffers->rb_lock);1376 spin_unlock(&buffers->rb_lock);
1436}1377 if (rep)
1437 1378 rpcrdma_destroy_rep(rep);
1438/*
1439 * Recover reply buffers from pool.
1440 * This happens when recovering from disconnect.
1441 */
1442void
1443rpcrdma_recv_buffer_get(struct rpcrdma_req *req)
1444{
1445 struct rpcrdma_buffer *buffers = req->rl_buffer;
1446
1447 spin_lock(&buffers->rb_lock);
1448 req->rl_reply = rpcrdma_buffer_get_rep(buffers);
1449 spin_unlock(&buffers->rb_lock);
1450}1379}
1451 1380
1452/*1381/*
@@ -1458,10 +1387,13 @@ rpcrdma_recv_buffer_put(struct rpcrdma_rep *rep) · 5 unmodified lines
1458{1387{
1459 struct rpcrdma_buffer *buffers = &rep->rr_rxprt->rx_buf;1388 struct rpcrdma_buffer *buffers = &rep->rr_rxprt->rx_buf;
1460 1389
1461 spin_lock(&buffers->rb_lock);1390 if (!rep->rr_temp) {
1462 buffers->rb_recv_count--;1391 spin_lock(&buffers->rb_lock);
1463 list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs);1392 list_add(&rep->rr_list, &buffers->rb_recv_bufs);
1464 spin_unlock(&buffers->rb_lock);1393 spin_unlock(&buffers->rb_lock);
1394 } else {
1395 rpcrdma_destroy_rep(rep);
1396 }
1465}1397}
1466 1398
1467/**1399/**
@@ -1557,13 +1489,6 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia, · 89 unmodified lines
1557 struct ib_send_wr *send_wr = &req->rl_sendctx->sc_wr;1489 struct ib_send_wr *send_wr = &req->rl_sendctx->sc_wr;
1558 int rc;1490 int rc;
1559 1491
1560 if (req->rl_reply) {
1561 rc = rpcrdma_ep_post_recv(ia, req->rl_reply);
1562 if (rc)
1563 return rc;
1564 req->rl_reply = NULL;
1565 }
1566
1567 if (!ep->rep_send_count ||1492 if (!ep->rep_send_count ||
1568 test_bit(RPCRDMA_REQ_F_TX_RESOURCES, &req->rl_flags)) {1493 test_bit(RPCRDMA_REQ_F_TX_RESOURCES, &req->rl_flags)) {
1569 send_wr->send_flags |= IB_SEND_SIGNALED;1494 send_wr->send_flags |= IB_SEND_SIGNALED;
@@ -1580,61 +1505,69 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia, · 10 unmodified lines
1580 return 0;1505 return 0;
1581}1506}
1582 1507
1583int
1584rpcrdma_ep_post_recv(struct rpcrdma_ia *ia,
1585 struct rpcrdma_rep *rep)
1586{
1587 struct ib_recv_wr *recv_wr_fail;
1588 int rc;
1589
1590 if (!rpcrdma_dma_map_regbuf(ia, rep->rr_rdmabuf))
1591 goto out_map;
1592 rc = ib_post_recv(ia->ri_id->qp, &rep->rr_recv_wr, &recv_wr_fail);
1593 trace_xprtrdma_post_recv(rep, rc);
1594 if (rc)
1595 return -ENOTCONN;
1596 return 0;
1597
1598out_map:
1599 pr_err("rpcrdma: failed to DMA map the Receive buffer\n");
1600 return -EIO;
1601}
1602
1603/**1508/**
1604 * rpcrdma_ep_post_extra_recv - Post buffers for incoming backchannel requests1509 * rpcrdma_post_recvs - Maybe post some Receive buffers
1605 * @r_xprt: transport associated with these backchannel resources1510 * @r_xprt: controlling transport
1606 * @count: minimum number of incoming requests expected1511 * @temp: when true, allocate temp rpcrdma_rep objects
1607 *1512 *
1608 * Returns zero if all requested buffers were posted, or a negative errno.
1609 */1513 */
1610int1514void
1611rpcrdma_ep_post_extra_recv(struct rpcrdma_xprt *r_xprt, unsigned int count)1515rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp)
1612{1516{
1613 struct rpcrdma_buffer *buffers = &r_xprt->rx_buf;1517 struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
1614 struct rpcrdma_ia *ia = &r_xprt->rx_ia;1518 struct ib_recv_wr *wr, *bad_wr;
1615 struct rpcrdma_rep *rep;1519 int needed, count, rc;
1616 int rc;
1617 1520
1618 while (count--) {1521 needed = buf->rb_credits + (buf->rb_bc_srv_max_requests << 1);
1619 spin_lock(&buffers->rb_lock);1522 if (buf->rb_posted_receives > needed)
1620 if (list_empty(&buffers->rb_recv_bufs))1523 return;
1621 goto out_reqbuf;1524 needed -= buf->rb_posted_receives;
1622 rep = rpcrdma_buffer_get_rep_locked(buffers);
1623 spin_unlock(&buffers->rb_lock);
1624 1525
1625 rc = rpcrdma_ep_post_recv(ia, rep);1526 count = 0;
1626 if (rc)1527 wr = NULL;
1627 goto out_rc;1528 while (needed) {
1628 }1529 struct rpcrdma_regbuf *rb;
1530 struct rpcrdma_rep *rep;
1629 1531
1630 return 0;1532 spin_lock(&buf->rb_lock);
1533 rep = list_first_entry_or_null(&buf->rb_recv_bufs,
1534 struct rpcrdma_rep, rr_list);
1535 if (likely(rep))
1536 list_del(&rep->rr_list);
1537 spin_unlock(&buf->rb_lock);
1538 if (!rep) {
1539 if (rpcrdma_create_rep(r_xprt, temp))
1540 break;
1541 continue;
1542 }
1631 1543
1632out_reqbuf:1544 rb = rep->rr_rdmabuf;
1633 spin_unlock(&buffers->rb_lock);1545 if (!rpcrdma_regbuf_is_mapped(rb)) {
1634 trace_xprtrdma_noreps(r_xprt);1546 if (!__rpcrdma_dma_map_regbuf(&r_xprt->rx_ia, rb)) {
1635 return -ENOMEM;1547 rpcrdma_recv_buffer_put(rep);
1548 break;
1549 }
1550 }
1636 1551
1637out_rc:1552 trace_xprtrdma_post_recv(rep->rr_recv_wr.wr_cqe);
1638 rpcrdma_recv_buffer_put(rep);1553 rep->rr_recv_wr.next = wr;
1639 return rc;1554 wr = &rep->rr_recv_wr;
1555 ++count;
1556 --needed;
1557 }
1558 if (!count)
1559 return;
1560
1561 rc = ib_post_recv(r_xprt->rx_ia.ri_id->qp, wr, &bad_wr);
1562 if (rc) {
1563 for (wr = bad_wr; wr; wr = wr->next) {
1564 struct rpcrdma_rep *rep;
1565
1566 rep = container_of(wr, struct rpcrdma_rep, rr_recv_wr);
1567 rpcrdma_recv_buffer_put(rep);
1568 --count;
1569 }
1570 }
1571 buf->rb_posted_receives += count;
1572 trace_xprtrdma_post_recvs(r_xprt, count, rc);
1640}1573}
net/sunrpc/xprtrdma/xprt_rdma.h+12−14
@@ -1,3 +1,4 @@
1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
1/*2/*
2 * Copyright (c) 2014-2017 Oracle. All rights reserved.3 * Copyright (c) 2014-2017 Oracle. All rights reserved.
3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.4 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -196,6 +197,7 @@ struct rpcrdma_rep { · 192 unmodified lines
196 __be32 rr_proc;197 __be32 rr_proc;
197 int rr_wc_flags;198 int rr_wc_flags;
198 u32 rr_inv_rkey;199 u32 rr_inv_rkey;
200 bool rr_temp;
199 struct rpcrdma_regbuf *rr_rdmabuf;201 struct rpcrdma_regbuf *rr_rdmabuf;
200 struct rpcrdma_xprt *rr_rxprt;202 struct rpcrdma_xprt *rr_rxprt;
201 struct work_struct rr_work;203 struct work_struct rr_work;
@@ -334,6 +336,7 @@ enum { · 132 unmodified lines
334struct rpcrdma_buffer;336struct rpcrdma_buffer;
335struct rpcrdma_req {337struct rpcrdma_req {
336 struct list_head rl_list;338 struct list_head rl_list;
339 struct rpc_rqst rl_slot;
337 struct rpcrdma_buffer *rl_buffer;340 struct rpcrdma_buffer *rl_buffer;
338 struct rpcrdma_rep *rl_reply;341 struct rpcrdma_rep *rl_reply;
339 struct xdr_stream rl_stream;342 struct xdr_stream rl_stream;
@@ -356,16 +359,10 @@ enum { · 16 unmodified lines
356 RPCRDMA_REQ_F_TX_RESOURCES,359 RPCRDMA_REQ_F_TX_RESOURCES,
357};360};
358 361
359static inline void
360rpcrdma_set_xprtdata(struct rpc_rqst *rqst, struct rpcrdma_req *req)
361{
362 rqst->rq_xprtdata = req;
363}
364
365static inline struct rpcrdma_req *362static inline struct rpcrdma_req *
366rpcr_to_rdmar(const struct rpc_rqst *rqst)363rpcr_to_rdmar(const struct rpc_rqst *rqst)
367{364{
368 return rqst->rq_xprtdata;365 return container_of(rqst, struct rpcrdma_req, rl_slot);
369}366}
370 367
371static inline void368static inline void
@@ -401,11 +398,12 @@ struct rpcrdma_buffer { · 29 unmodified lines
401 struct rpcrdma_sendctx **rb_sc_ctxs;398 struct rpcrdma_sendctx **rb_sc_ctxs;
402 399
403 spinlock_t rb_lock; /* protect buf lists */400 spinlock_t rb_lock; /* protect buf lists */
404 int rb_send_count, rb_recv_count;
405 struct list_head rb_send_bufs;401 struct list_head rb_send_bufs;
406 struct list_head rb_recv_bufs;402 struct list_head rb_recv_bufs;
403 unsigned long rb_flags;
407 u32 rb_max_requests;404 u32 rb_max_requests;
408 u32 rb_credits; /* most recent credit grant */405 u32 rb_credits; /* most recent credit grant */
406 int rb_posted_receives;
409 407
410 u32 rb_bc_srv_max_requests;408 u32 rb_bc_srv_max_requests;
411 spinlock_t rb_reqslock; /* protect rb_allreqs */409 spinlock_t rb_reqslock; /* protect rb_allreqs */
@@ -420,6 +418,11 @@ struct rpcrdma_buffer { · 8 unmodified lines
420};418};
421#define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia)419#define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia)
422 420
421/* rb_flags */
422enum {
423 RPCRDMA_BUF_F_EMPTY_SCQ = 0,
424};
425
423/*426/*
424 * Internal structure for transport instance creation. This427 * Internal structure for transport instance creation. This
425 * exists primarily for modularity.428 * exists primarily for modularity.
@@ -561,18 +564,16 @@ void rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *); · 135 unmodified lines
561 564
562int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *,565int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *,
563 struct rpcrdma_req *);566 struct rpcrdma_req *);
564int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_rep *);567void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp);
565 568
566/*569/*
567 * Buffer calls - xprtrdma/verbs.c570 * Buffer calls - xprtrdma/verbs.c
568 */571 */
569struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *);572struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *);
570void rpcrdma_destroy_req(struct rpcrdma_req *);573void rpcrdma_destroy_req(struct rpcrdma_req *);
571int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt);
572int rpcrdma_buffer_create(struct rpcrdma_xprt *);574int rpcrdma_buffer_create(struct rpcrdma_xprt *);
573void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);575void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);
574struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf);576struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf);
575void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc);
576 577
577struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt);578struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt);
578void rpcrdma_mr_put(struct rpcrdma_mr *mr);579void rpcrdma_mr_put(struct rpcrdma_mr *mr);
@@ -581,7 +582,6 @@ void rpcrdma_mr_defer_recovery(struct rpcrdma_mr *mr); · 2 unmodified lines
581 582
582struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *);583struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *);
583void rpcrdma_buffer_put(struct rpcrdma_req *);584void rpcrdma_buffer_put(struct rpcrdma_req *);
584void rpcrdma_recv_buffer_get(struct rpcrdma_req *);
585void rpcrdma_recv_buffer_put(struct rpcrdma_rep *);585void rpcrdma_recv_buffer_put(struct rpcrdma_rep *);
586 586
587struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(size_t, enum dma_data_direction,587struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(size_t, enum dma_data_direction,
@@ -603,8 +603,6 @@ rpcrdma_dma_map_regbuf(struct rpcrdma_ia *ia, struct rpcrdma_regbuf *rb) · 15 unmodified lines
603 return __rpcrdma_dma_map_regbuf(ia, rb);603 return __rpcrdma_dma_map_regbuf(ia, rb);
604}604}
605 605
606int rpcrdma_ep_post_extra_recv(struct rpcrdma_xprt *, unsigned int);
607
608int rpcrdma_alloc_wq(void);606int rpcrdma_alloc_wq(void);
609void rpcrdma_destroy_wq(void);607void rpcrdma_destroy_wq(void);
610 608
net/sunrpc/xprtsock.c+4−0
@@ -2763,6 +2763,7 @@ static const struct rpc_xprt_ops xs_local_ops = { · 2762 unmodified lines
2763 .reserve_xprt = xprt_reserve_xprt,2763 .reserve_xprt = xprt_reserve_xprt,
2764 .release_xprt = xs_tcp_release_xprt,2764 .release_xprt = xs_tcp_release_xprt,
2765 .alloc_slot = xprt_alloc_slot,2765 .alloc_slot = xprt_alloc_slot,
2766 .free_slot = xprt_free_slot,
2766 .rpcbind = xs_local_rpcbind,2767 .rpcbind = xs_local_rpcbind,
2767 .set_port = xs_local_set_port,2768 .set_port = xs_local_set_port,
2768 .connect = xs_local_connect,2769 .connect = xs_local_connect,
@@ -2782,6 +2783,7 @@ static const struct rpc_xprt_ops xs_udp_ops = { · 13 unmodified lines
2782 .reserve_xprt = xprt_reserve_xprt_cong,2783 .reserve_xprt = xprt_reserve_xprt_cong,
2783 .release_xprt = xprt_release_xprt_cong,2784 .release_xprt = xprt_release_xprt_cong,
2784 .alloc_slot = xprt_alloc_slot,2785 .alloc_slot = xprt_alloc_slot,
2786 .free_slot = xprt_free_slot,
2785 .rpcbind = rpcb_getport_async,2787 .rpcbind = rpcb_getport_async,
2786 .set_port = xs_set_port,2788 .set_port = xs_set_port,
2787 .connect = xs_connect,2789 .connect = xs_connect,
@@ -2803,6 +2805,7 @@ static const struct rpc_xprt_ops xs_tcp_ops = { · 15 unmodified lines
2803 .reserve_xprt = xprt_reserve_xprt,2805 .reserve_xprt = xprt_reserve_xprt,
2804 .release_xprt = xs_tcp_release_xprt,2806 .release_xprt = xs_tcp_release_xprt,
2805 .alloc_slot = xprt_lock_and_alloc_slot,2807 .alloc_slot = xprt_lock_and_alloc_slot,
2808 .free_slot = xprt_free_slot,
2806 .rpcbind = rpcb_getport_async,2809 .rpcbind = rpcb_getport_async,
2807 .set_port = xs_set_port,2810 .set_port = xs_set_port,
2808 .connect = xs_connect,2811 .connect = xs_connect,
@@ -2834,6 +2837,7 @@ static const struct rpc_xprt_ops bc_tcp_ops = { · 25 unmodified lines
2834 .reserve_xprt = xprt_reserve_xprt,2837 .reserve_xprt = xprt_reserve_xprt,
2835 .release_xprt = xprt_release_xprt,2838 .release_xprt = xprt_release_xprt,
2836 .alloc_slot = xprt_alloc_slot,2839 .alloc_slot = xprt_alloc_slot,
2840 .free_slot = xprt_free_slot,
2837 .buf_alloc = bc_malloc,2841 .buf_alloc = bc_malloc,
2838 .buf_free = bc_free,2842 .buf_free = bc_free,
2839 .send_request = bc_send_request,2843 .send_request = bc_send_request,