summaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2017-10-16 15:01:39 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2017-11-17 13:47:55 -0500
commitbe798f9082aa54524b209fac2c8164c81cd28f77 (patch)
tree146ed327e4138a89734e63ffe7bc839604d11bfd /net/sunrpc
parentd8f532d20ee43a0117284798d486bc4f98e3b196 (diff)
xprtrdma: Decode credits field in rpcrdma_reply_handler
We need to decode and save the incoming rdma_credits field _after_ we know that the direction of the message is "forward direction Reply". Otherwise, the credits value in reverse direction Calls is also used to update the forward direction credits. It is safe to decode the rdma_credits field in rpcrdma_reply_handler now that rpcrdma_reply_handler is single-threaded. Receives complete in the same order as they were sent on the NFS server. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c14
-rw-r--r--net/sunrpc/xprtrdma/verbs.c25
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h2
3 files changed, 14 insertions, 27 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 430f8b5a8c43..b8818c09a621 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -1244,7 +1244,7 @@ void rpcrdma_complete_rqst(struct rpcrdma_rep *rep)
1244out: 1244out:
1245 spin_lock(&xprt->recv_lock); 1245 spin_lock(&xprt->recv_lock);
1246 cwnd = xprt->cwnd; 1246 cwnd = xprt->cwnd;
1247 xprt->cwnd = atomic_read(&r_xprt->rx_buf.rb_credits) << RPC_CWNDSHIFT; 1247 xprt->cwnd = r_xprt->rx_buf.rb_credits << RPC_CWNDSHIFT;
1248 if (xprt->cwnd > cwnd) 1248 if (xprt->cwnd > cwnd)
1249 xprt_release_rqst_cong(rqst->rq_task); 1249 xprt_release_rqst_cong(rqst->rq_task);
1250 1250
@@ -1297,8 +1297,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
1297{ 1297{
1298 struct rpcrdma_xprt *r_xprt = rep->rr_rxprt; 1298 struct rpcrdma_xprt *r_xprt = rep->rr_rxprt;
1299 struct rpc_xprt *xprt = &r_xprt->rx_xprt; 1299 struct rpc_xprt *xprt = &r_xprt->rx_xprt;
1300 struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
1300 struct rpcrdma_req *req; 1301 struct rpcrdma_req *req;
1301 struct rpc_rqst *rqst; 1302 struct rpc_rqst *rqst;
1303 u32 credits;
1302 __be32 *p; 1304 __be32 *p;
1303 1305
1304 dprintk("RPC: %s: incoming rep %p\n", __func__, rep); 1306 dprintk("RPC: %s: incoming rep %p\n", __func__, rep);
@@ -1315,7 +1317,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
1315 goto out_shortreply; 1317 goto out_shortreply;
1316 rep->rr_xid = *p++; 1318 rep->rr_xid = *p++;
1317 rep->rr_vers = *p++; 1319 rep->rr_vers = *p++;
1318 p++; /* credits */ 1320 credits = be32_to_cpu(*p++);
1319 rep->rr_proc = *p++; 1321 rep->rr_proc = *p++;
1320 1322
1321 if (rep->rr_vers != rpcrdma_version) 1323 if (rep->rr_vers != rpcrdma_version)
@@ -1332,7 +1334,15 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
1332 if (!rqst) 1334 if (!rqst)
1333 goto out_norqst; 1335 goto out_norqst;
1334 xprt_pin_rqst(rqst); 1336 xprt_pin_rqst(rqst);
1337
1338 if (credits == 0)
1339 credits = 1; /* don't deadlock */
1340 else if (credits > buf->rb_max_requests)
1341 credits = buf->rb_max_requests;
1342 buf->rb_credits = credits;
1343
1335 spin_unlock(&xprt->recv_lock); 1344 spin_unlock(&xprt->recv_lock);
1345
1336 req = rpcr_to_rdmar(rqst); 1346 req = rpcr_to_rdmar(rqst);
1337 req->rl_reply = rep; 1347 req->rl_reply = rep;
1338 rep->rr_rqst = rqst; 1348 rep->rr_rqst = rqst;
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index d45695408df3..247b00b715c2 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -133,25 +133,6 @@ rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
133 wc->status, wc->vendor_err); 133 wc->status, wc->vendor_err);
134} 134}
135 135
136/* Perform basic sanity checking to avoid using garbage
137 * to update the credit grant value.
138 */
139static void
140rpcrdma_update_granted_credits(struct rpcrdma_rep *rep)
141{
142 struct rpcrdma_buffer *buffer = &rep->rr_rxprt->rx_buf;
143 __be32 *p = rep->rr_rdmabuf->rg_base;
144 u32 credits;
145
146 credits = be32_to_cpup(p + 2);
147 if (credits == 0)
148 credits = 1; /* don't deadlock */
149 else if (credits > buffer->rb_max_requests)
150 credits = buffer->rb_max_requests;
151
152 atomic_set(&buffer->rb_credits, credits);
153}
154
155/** 136/**
156 * rpcrdma_wc_receive - Invoked by RDMA provider for each polled Receive WC 137 * rpcrdma_wc_receive - Invoked by RDMA provider for each polled Receive WC
157 * @cq: completion queue (ignored) 138 * @cq: completion queue (ignored)
@@ -181,9 +162,6 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
181 rdmab_addr(rep->rr_rdmabuf), 162 rdmab_addr(rep->rr_rdmabuf),
182 wc->byte_len, DMA_FROM_DEVICE); 163 wc->byte_len, DMA_FROM_DEVICE);
183 164
184 if (wc->byte_len >= RPCRDMA_HDRLEN_ERR)
185 rpcrdma_update_granted_credits(rep);
186
187out_schedule: 165out_schedule:
188 rpcrdma_reply_handler(rep); 166 rpcrdma_reply_handler(rep);
189 return; 167 return;
@@ -295,7 +273,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
295 case RDMA_CM_EVENT_DISCONNECTED: 273 case RDMA_CM_EVENT_DISCONNECTED:
296 connstate = -ECONNABORTED; 274 connstate = -ECONNABORTED;
297connected: 275connected:
298 atomic_set(&xprt->rx_buf.rb_credits, 1); 276 xprt->rx_buf.rb_credits = 1;
299 ep->rep_connected = connstate; 277 ep->rep_connected = connstate;
300 rpcrdma_conn_func(ep); 278 rpcrdma_conn_func(ep);
301 wake_up_all(&ep->rep_connect_wait); 279 wake_up_all(&ep->rep_connect_wait);
@@ -995,7 +973,6 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
995 973
996 buf->rb_max_requests = r_xprt->rx_data.max_requests; 974 buf->rb_max_requests = r_xprt->rx_data.max_requests;
997 buf->rb_bc_srv_max_requests = 0; 975 buf->rb_bc_srv_max_requests = 0;
998 atomic_set(&buf->rb_credits, 1);
999 spin_lock_init(&buf->rb_mwlock); 976 spin_lock_init(&buf->rb_mwlock);
1000 spin_lock_init(&buf->rb_lock); 977 spin_lock_init(&buf->rb_lock);
1001 spin_lock_init(&buf->rb_recovery_lock); 978 spin_lock_init(&buf->rb_recovery_lock);
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index a85bcd19b37a..0e0ae6195a5b 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -407,7 +407,7 @@ struct rpcrdma_buffer {
407 struct list_head rb_send_bufs; 407 struct list_head rb_send_bufs;
408 struct list_head rb_recv_bufs; 408 struct list_head rb_recv_bufs;
409 u32 rb_max_requests; 409 u32 rb_max_requests;
410 atomic_t rb_credits; /* most recent credit grant */ 410 u32 rb_credits; /* most recent credit grant */
411 411
412 u32 rb_bc_srv_max_requests; 412 u32 rb_bc_srv_max_requests;
413 spinlock_t rb_reqslock; /* protect rb_allreqs */ 413 spinlock_t rb_reqslock; /* protect rb_allreqs */