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
Unified · Split
| @@ -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. |
| @@ -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 | |||
| 324 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args); | 325 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args); |
| 325 | void xprt_connect(struct rpc_task *task); | 326 | void xprt_connect(struct rpc_task *task); |
| 326 | void xprt_reserve(struct rpc_task *task); | 327 | void xprt_reserve(struct rpc_task *task); |
| 328 | void xprt_request_init(struct rpc_task *task); | ||
| 327 | void xprt_retry_reserve(struct rpc_task *task); | 329 | void xprt_retry_reserve(struct rpc_task *task); |
| 328 | int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); | 330 | int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
| 329 | int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); | 331 | int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
| 330 | void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); | 332 | void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); |
| 333 | void xprt_free_slot(struct rpc_xprt *xprt, | ||
| 334 | struct rpc_rqst *req); | ||
| 331 | void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); | 335 | void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); |
| 332 | bool xprt_prepare_transmit(struct rpc_task *task); | 336 | bool xprt_prepare_transmit(struct rpc_task *task); |
| 333 | void xprt_transmit(struct rpc_task *task); | 337 | void xprt_transmit(struct rpc_task *task); |
| @@ -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 | * |
| @@ -528,24 +528,54 @@ TRACE_EVENT(xprtrdma_post_send, · 527 unmodified lines | |||
| 528 | 528 | ||
| 529 | TRACE_EVENT(xprtrdma_post_recv, | 529 | TRACE_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 | |||
| 549 | TRACE_EVENT(xprtrdma_post_recvs, | ||
| 550 | TP_PROTO( | ||
| 551 | const struct rpcrdma_xprt *r_xprt, | ||
| 552 | unsigned int count, | ||
| 532 | int status | 553 | 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->status | 577 | __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 | ||
| 585 | TRACE_EVENT(xprtrdma_wc_receive, | 615 | TRACE_EVENT(xprtrdma_wc_receive, |
| 586 | TP_PROTO( | 616 | TP_PROTO( |
| 587 | const struct rpcrdma_rep *rep, | ||
| 588 | const struct ib_wc *wc | 617 | 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_err | 644 | __entry->status, __entry->vendor_err |
| 611 | ) | 645 | ) |
| @@ -616,6 +650,7 @@ DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li); · 4 unmodified lines | |||
| 616 | DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li_wake); | 650 | DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li_wake); |
| 617 | 651 | ||
| 618 | DEFINE_MR_EVENT(xprtrdma_localinv); | 652 | DEFINE_MR_EVENT(xprtrdma_localinv); |
| 653 | DEFINE_MR_EVENT(xprtrdma_dma_map); | ||
| 619 | DEFINE_MR_EVENT(xprtrdma_dma_unmap); | 654 | DEFINE_MR_EVENT(xprtrdma_dma_unmap); |
| 620 | DEFINE_MR_EVENT(xprtrdma_remoteinv); | 655 | DEFINE_MR_EVENT(xprtrdma_remoteinv); |
| 621 | DEFINE_MR_EVENT(xprtrdma_recover_mr); | 656 | DEFINE_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 | ||
| 851 | DEFINE_RXPRT_EVENT(xprtrdma_noreps); | ||
| 852 | |||
| 853 | /** | 883 | /** |
| 854 | ** Callback events | 884 | ** Callback events |
| 855 | **/ | 885 | **/ |
| @@ -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 | } |
| @@ -66,7 +66,7 @@ · 65 unmodified lines | |||
| 66 | * Local functions | 66 | * Local functions |
| 67 | */ | 67 | */ |
| 68 | static void xprt_init(struct rpc_xprt *xprt, struct net *net); | 68 | static void xprt_init(struct rpc_xprt *xprt, struct net *net); |
| 69 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); | 69 | static __be32 xprt_alloc_xid(struct rpc_xprt *xprt); |
| 70 | static void xprt_connect_status(struct rpc_task *task); | 70 | static void xprt_connect_status(struct rpc_task *task); |
| 71 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 71 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
| 72 | static void __xprt_put_cong(struct rpc_xprt *, struct rpc_rqst *); | 72 | static 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; |
| 991 | out_unlock: | 993 | out_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 | |||
| 1163 | out_init_req: | 1165 | out_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 | } |
| 1171 | EXPORT_SYMBOL_GPL(xprt_alloc_slot); | 1173 | EXPORT_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 | } |
| 1185 | EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); | 1187 | EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); |
| 1186 | 1188 | ||
| 1187 | static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) | 1189 | void 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 | } |
| 1199 | EXPORT_SYMBOL_GPL(xprt_free_slot); | ||
| 1197 | 1200 | ||
| 1198 | static void xprt_free_all_slots(struct rpc_xprt *xprt) | 1201 | static 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 | ||
| 1306 | static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | 1309 | void 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 | else | 1380 | else |
| 1378 | xprt_free_bc_request(req); | 1381 | xprt_free_bc_request(req); |
| 1379 | } | 1382 | } |
| @@ -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 | ||
| 36 | static int rpcrdma_bc_setup_rqst(struct rpcrdma_xprt *r_xprt, | 34 | static 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 | ||
| 57 | out_fail: | 69 | out_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 | */ | ||
| 66 | static 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 requests | 75 | * xprt_rdma_bc_setup - Pre-allocate resources for handling backchannel requests |
| 81 | * @xprt: transport associated with these backchannel resources | 76 | * @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 | |||
| 86 | int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs) | 81 | int 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 the | 86 | /* 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 | */ |
| 276 | void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst) | 245 | void 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); |
| @@ -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 | */ | ||
| 159 | static int | 165 | static int |
| 160 | fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, | 166 | fmr_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]); |
| @@ -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 | */ | ||
| 205 | static int | 215 | static int |
| 206 | frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, | 216 | frwr_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); |
| @@ -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 | */ |
| @@ -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_TRANS | 55 | # define RPCDBG_FACILITY RPCDBG_TRANS |
| 55 | #endif | 56 | #endif |
| 56 | 57 | ||
| 57 | static 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 message | 58 | /* 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 a | 60 | * 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 | |||
| 381 | out_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 list | 375 | /* 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 | |||
| 449 | out_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 array | 438 | /* 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 | |||
| 512 | out_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 | ||
| 885 | out_err: | 863 | out_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 | ||
| 1027 | out_short: | 1013 | out_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 | ||
| 1384 | out_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 | |||
| 1392 | out_badversion: | 1370 | out_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 | */ |
| 1410 | repost: | 1388 | repost: |
| 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)) | 1390 | out_badstatus: |
| 1413 | rpcrdma_recv_buffer_put(rep); | 1391 | rpcrdma_recv_buffer_put(rep); |
| 1414 | } | 1392 | } |
| @@ -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, |
| @@ -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 | */ | ||
| 548 | static void | ||
| 549 | xprt_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 | |||
| 561 | out_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 | */ | ||
| 572 | static void | ||
| 573 | xprt_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 | |||
| 540 | static bool | 580 | static bool |
| 541 | rpcrdma_get_sendbuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, | 581 | rpcrdma_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 | ||
| 632 | out_fail: | 667 | out_fail: |
| 633 | rpcrdma_buffer_put(req); | ||
| 634 | out_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 | |||
| 779 | static const struct rpc_xprt_ops xprt_rdma_procs = { | 808 | static 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, |
| @@ -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 functions | 73 | * internal functions |
| 73 | */ | 74 | */ |
| 75 | static void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc); | ||
| 74 | static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt); | 76 | static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt); |
| 75 | static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf); | 77 | static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf); |
| 78 | static int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp); | ||
| 76 | static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb); | 79 | static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb); |
| 77 | 80 | ||
| 78 | struct workqueue_struct *rpcrdma_receive_wq __read_mostly; | 81 | struct 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 | ||
| 747 | retry: | 733 | retry: |
| @@ -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 | ||
| 792 | out: | 777 | out: |
| 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 is | 936 | * 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 | */ |
| 968 | void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc) | 954 | static void |
| 955 | rpcrdma_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 | ||
| 989 | static void | 981 | static 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 | /** | 1092 | static int |
| 1101 | * rpcrdma_create_rep - Allocate an rpcrdma_rep object | 1093 | rpcrdma_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 | */ | ||
| 1106 | int | ||
| 1107 | rpcrdma_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 | ||
| 1203 | static struct rpcrdma_req * | ||
| 1204 | rpcrdma_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 | |||
| 1214 | static struct rpcrdma_rep * | ||
| 1215 | rpcrdma_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 | |||
| 1225 | static void | 1186 | static void |
| 1226 | rpcrdma_destroy_rep(struct rpcrdma_rep *rep) | 1187 | rpcrdma_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 | ||
| 1374 | static struct rpcrdma_rep * | 1335 | /** |
| 1375 | rpcrdma_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 | */ |
| 1396 | struct rpcrdma_req * | 1341 | struct rpcrdma_req * |
| 1397 | rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) | 1342 | rpcrdma_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 | |||
| 1411 | out_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 | */ |
| 1420 | void | 1360 | void |
| 1421 | rpcrdma_buffer_put(struct rpcrdma_req *req) | 1361 | rpcrdma_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 | */ | ||
| 1442 | void | ||
| 1443 | rpcrdma_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 | ||
| 1583 | int | ||
| 1584 | rpcrdma_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 | |||
| 1598 | out_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 requests | 1509 | * rpcrdma_post_recvs - Maybe post some Receive buffers |
| 1605 | * @r_xprt: transport associated with these backchannel resources | 1510 | * @r_xprt: controlling transport |
| 1606 | * @count: minimum number of incoming requests expected | 1511 | * @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 | */ |
| 1610 | int | 1514 | void |
| 1611 | rpcrdma_ep_post_extra_recv(struct rpcrdma_xprt *r_xprt, unsigned int count) | 1515 | rpcrdma_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 | ||
| 1632 | out_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 | ||
| 1637 | out_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 | } |
| @@ -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 | |||
| 334 | struct rpcrdma_buffer; | 336 | struct rpcrdma_buffer; |
| 335 | struct rpcrdma_req { | 337 | struct 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 | ||
| 359 | static inline void | ||
| 360 | rpcrdma_set_xprtdata(struct rpc_rqst *rqst, struct rpcrdma_req *req) | ||
| 361 | { | ||
| 362 | rqst->rq_xprtdata = req; | ||
| 363 | } | ||
| 364 | |||
| 365 | static inline struct rpcrdma_req * | 362 | static inline struct rpcrdma_req * |
| 366 | rpcr_to_rdmar(const struct rpc_rqst *rqst) | 363 | rpcr_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 | ||
| 371 | static inline void | 368 | static 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 */ | ||
| 422 | enum { | ||
| 423 | RPCRDMA_BUF_F_EMPTY_SCQ = 0, | ||
| 424 | }; | ||
| 425 | |||
| 423 | /* | 426 | /* |
| 424 | * Internal structure for transport instance creation. This | 427 | * 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 | ||
| 562 | int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, | 565 | int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, |
| 563 | struct rpcrdma_req *); | 566 | struct rpcrdma_req *); |
| 564 | int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_rep *); | 567 | void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp); |
| 565 | 568 | ||
| 566 | /* | 569 | /* |
| 567 | * Buffer calls - xprtrdma/verbs.c | 570 | * Buffer calls - xprtrdma/verbs.c |
| 568 | */ | 571 | */ |
| 569 | struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *); | 572 | struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *); |
| 570 | void rpcrdma_destroy_req(struct rpcrdma_req *); | 573 | void rpcrdma_destroy_req(struct rpcrdma_req *); |
| 571 | int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt); | ||
| 572 | int rpcrdma_buffer_create(struct rpcrdma_xprt *); | 574 | int rpcrdma_buffer_create(struct rpcrdma_xprt *); |
| 573 | void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); | 575 | void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); |
| 574 | struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf); | 576 | struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf); |
| 575 | void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc); | ||
| 576 | 577 | ||
| 577 | struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt); | 578 | struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt); |
| 578 | void rpcrdma_mr_put(struct rpcrdma_mr *mr); | 579 | void 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 | ||
| 582 | struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); | 583 | struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); |
| 583 | void rpcrdma_buffer_put(struct rpcrdma_req *); | 584 | void rpcrdma_buffer_put(struct rpcrdma_req *); |
| 584 | void rpcrdma_recv_buffer_get(struct rpcrdma_req *); | ||
| 585 | void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); | 585 | void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); |
| 586 | 586 | ||
| 587 | struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(size_t, enum dma_data_direction, | 587 | struct 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 | ||
| 606 | int rpcrdma_ep_post_extra_recv(struct rpcrdma_xprt *, unsigned int); | ||
| 607 | |||
| 608 | int rpcrdma_alloc_wq(void); | 606 | int rpcrdma_alloc_wq(void); |
| 609 | void rpcrdma_destroy_wq(void); | 607 | void rpcrdma_destroy_wq(void); |
| 610 | 608 | ||
| @@ -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, |