aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2017-12-14 20:56:09 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-01-16 11:19:41 -0500
commitd698c4a02ee02053bbebe051322ff427a2dad56a (patch)
tree61e79e7e1319fa679eef870f60fb7dad0f111caa
parent03ac1a76ce5e5a6052a421e1d6a5c97778e88a8c (diff)
xprtrdma: Fix backchannel allocation of extra rpcrdma_reps
The backchannel code uses rpcrdma_recv_buffer_put to add new reps to the free rep list. This also decrements rb_recv_count, which spoofs the receive overrun logic in rpcrdma_buffer_get_rep. Commit 9b06688bc3b9 ("xprtrdma: Fix additional uses of spin_lock_irqsave(rb_lock)") replaced the original open-coded list_add with a call to rpcrdma_recv_buffer_put(), but then a year later, commit 05c974669ece ("xprtrdma: Fix receive buffer accounting") added rep accounting to rpcrdma_recv_buffer_put. It was an oversight to let the backchannel continue to use this function. The fix this, let's combine the "add to free list" logic with rpcrdma_create_rep. Also, do not allocate RPCRDMA_MAX_BC_REQUESTS rpcrdma_reps in rpcrdma_buffer_create and then allocate additional rpcrdma_reps in rpcrdma_bc_setup_reps. Allocating the extra reps during backchannel set-up is sufficient. Fixes: 05c974669ece ("xprtrdma: Fix receive buffer accounting") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--net/sunrpc/xprtrdma/backchannel.c12
-rw-r--r--net/sunrpc/xprtrdma/verbs.c32
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h2
3 files changed, 22 insertions, 24 deletions
diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c
index 8b818bb3518a..256c67b433c1 100644
--- a/net/sunrpc/xprtrdma/backchannel.c
+++ b/net/sunrpc/xprtrdma/backchannel.c
@@ -74,21 +74,13 @@ out_fail:
74static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt, 74static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt,
75 unsigned int count) 75 unsigned int count)
76{ 76{
77 struct rpcrdma_rep *rep;
78 int rc = 0; 77 int rc = 0;
79 78
80 while (count--) { 79 while (count--) {
81 rep = rpcrdma_create_rep(r_xprt); 80 rc = rpcrdma_create_rep(r_xprt);
82 if (IS_ERR(rep)) { 81 if (rc)
83 pr_err("RPC: %s: reply buffer alloc failed\n",
84 __func__);
85 rc = PTR_ERR(rep);
86 break; 82 break;
87 }
88
89 rpcrdma_recv_buffer_put(rep);
90 } 83 }
91
92 return rc; 84 return rc;
93} 85}
94 86
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 8607c029c0dd..6eecd9714051 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -1093,10 +1093,17 @@ rpcrdma_create_req(struct rpcrdma_xprt *r_xprt)
1093 return req; 1093 return req;
1094} 1094}
1095 1095
1096struct rpcrdma_rep * 1096/**
1097 * rpcrdma_create_rep - Allocate an rpcrdma_rep object
1098 * @r_xprt: controlling transport
1099 *
1100 * Returns 0 on success or a negative errno on failure.
1101 */
1102int
1097rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt) 1103rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
1098{ 1104{
1099 struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data; 1105 struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
1106 struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
1100 struct rpcrdma_rep *rep; 1107 struct rpcrdma_rep *rep;
1101 int rc; 1108 int rc;
1102 1109
@@ -1121,12 +1128,18 @@ rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
1121 rep->rr_recv_wr.wr_cqe = &rep->rr_cqe; 1128 rep->rr_recv_wr.wr_cqe = &rep->rr_cqe;
1122 rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov; 1129 rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
1123 rep->rr_recv_wr.num_sge = 1; 1130 rep->rr_recv_wr.num_sge = 1;
1124 return rep; 1131
1132 spin_lock(&buf->rb_lock);
1133 list_add(&rep->rr_list, &buf->rb_recv_bufs);
1134 spin_unlock(&buf->rb_lock);
1135 return 0;
1125 1136
1126out_free: 1137out_free:
1127 kfree(rep); 1138 kfree(rep);
1128out: 1139out:
1129 return ERR_PTR(rc); 1140 dprintk("RPC: %s: reply buffer %d alloc failed\n",
1141 __func__, rc);
1142 return rc;
1130} 1143}
1131 1144
1132int 1145int
@@ -1167,17 +1180,10 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
1167 } 1180 }
1168 1181
1169 INIT_LIST_HEAD(&buf->rb_recv_bufs); 1182 INIT_LIST_HEAD(&buf->rb_recv_bufs);
1170 for (i = 0; i < buf->rb_max_requests + RPCRDMA_MAX_BC_REQUESTS; i++) { 1183 for (i = 0; i <= buf->rb_max_requests; i++) {
1171 struct rpcrdma_rep *rep; 1184 rc = rpcrdma_create_rep(r_xprt);
1172 1185 if (rc)
1173 rep = rpcrdma_create_rep(r_xprt);
1174 if (IS_ERR(rep)) {
1175 dprintk("RPC: %s: reply buffer %d alloc failed\n",
1176 __func__, i);
1177 rc = PTR_ERR(rep);
1178 goto out; 1186 goto out;
1179 }
1180 list_add(&rep->rr_list, &buf->rb_recv_bufs);
1181 } 1187 }
1182 1188
1183 rc = rpcrdma_sendctxs_create(r_xprt); 1189 rc = rpcrdma_sendctxs_create(r_xprt);
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index 1342f743f1c4..3b63e61feae2 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -564,8 +564,8 @@ int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_rep *);
564 * Buffer calls - xprtrdma/verbs.c 564 * Buffer calls - xprtrdma/verbs.c
565 */ 565 */
566struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *); 566struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *);
567struct rpcrdma_rep *rpcrdma_create_rep(struct rpcrdma_xprt *);
568void rpcrdma_destroy_req(struct rpcrdma_req *); 567void rpcrdma_destroy_req(struct rpcrdma_req *);
568int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt);
569int rpcrdma_buffer_create(struct rpcrdma_xprt *); 569int rpcrdma_buffer_create(struct rpcrdma_xprt *);
570void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); 570void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);
571struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf); 571struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf);