|
@@ -741,52 +741,27 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
|
|
|
unsigned long cwnd;
|
|
|
u32 credits;
|
|
|
|
|
|
- /* Check status. If bad, signal disconnect and return rep to pool */
|
|
|
- if (rep->rr_len == ~0U) {
|
|
|
- rpcrdma_recv_buffer_put(rep);
|
|
|
- if (r_xprt->rx_ep.rep_connected == 1) {
|
|
|
- r_xprt->rx_ep.rep_connected = -EIO;
|
|
|
- rpcrdma_conn_func(&r_xprt->rx_ep);
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- if (rep->rr_len < RPCRDMA_HDRLEN_MIN) {
|
|
|
- dprintk("RPC: %s: short/invalid reply\n", __func__);
|
|
|
- goto repost;
|
|
|
- }
|
|
|
+ dprintk("RPC: %s: incoming rep %p\n", __func__, rep);
|
|
|
+
|
|
|
+ if (rep->rr_len == RPCRDMA_BAD_LEN)
|
|
|
+ goto out_badstatus;
|
|
|
+ if (rep->rr_len < RPCRDMA_HDRLEN_MIN)
|
|
|
+ goto out_shortreply;
|
|
|
+
|
|
|
headerp = rdmab_to_msg(rep->rr_rdmabuf);
|
|
|
- if (headerp->rm_vers != rpcrdma_version) {
|
|
|
- dprintk("RPC: %s: invalid version %d\n",
|
|
|
- __func__, be32_to_cpu(headerp->rm_vers));
|
|
|
- goto repost;
|
|
|
- }
|
|
|
+ if (headerp->rm_vers != rpcrdma_version)
|
|
|
+ goto out_badversion;
|
|
|
|
|
|
/* Get XID and try for a match. */
|
|
|
spin_lock(&xprt->transport_lock);
|
|
|
rqst = xprt_lookup_rqst(xprt, headerp->rm_xid);
|
|
|
- if (rqst == NULL) {
|
|
|
- spin_unlock(&xprt->transport_lock);
|
|
|
- dprintk("RPC: %s: reply 0x%p failed "
|
|
|
- "to match any request xid 0x%08x len %d\n",
|
|
|
- __func__, rep, be32_to_cpu(headerp->rm_xid),
|
|
|
- rep->rr_len);
|
|
|
-repost:
|
|
|
- r_xprt->rx_stats.bad_reply_count++;
|
|
|
- if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, &r_xprt->rx_ep, rep))
|
|
|
- rpcrdma_recv_buffer_put(rep);
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (!rqst)
|
|
|
+ goto out_nomatch;
|
|
|
|
|
|
/* get request object */
|
|
|
req = rpcr_to_rdmar(rqst);
|
|
|
- if (req->rl_reply) {
|
|
|
- spin_unlock(&xprt->transport_lock);
|
|
|
- dprintk("RPC: %s: duplicate reply 0x%p to RPC "
|
|
|
- "request 0x%p: xid 0x%08x\n", __func__, rep, req,
|
|
|
- be32_to_cpu(headerp->rm_xid));
|
|
|
- goto repost;
|
|
|
- }
|
|
|
+ if (req->rl_reply)
|
|
|
+ goto out_duplicate;
|
|
|
|
|
|
dprintk("RPC: %s: reply 0x%p completes request 0x%p\n"
|
|
|
" RPC request 0x%p xid 0x%08x\n",
|
|
@@ -883,8 +858,44 @@ badheader:
|
|
|
if (xprt->cwnd > cwnd)
|
|
|
xprt_release_rqst_cong(rqst->rq_task);
|
|
|
|
|
|
+ xprt_complete_rqst(rqst->rq_task, status);
|
|
|
+ spin_unlock(&xprt->transport_lock);
|
|
|
dprintk("RPC: %s: xprt_complete_rqst(0x%p, 0x%p, %d)\n",
|
|
|
__func__, xprt, rqst, status);
|
|
|
- xprt_complete_rqst(rqst->rq_task, status);
|
|
|
+ return;
|
|
|
+
|
|
|
+out_badstatus:
|
|
|
+ rpcrdma_recv_buffer_put(rep);
|
|
|
+ if (r_xprt->rx_ep.rep_connected == 1) {
|
|
|
+ r_xprt->rx_ep.rep_connected = -EIO;
|
|
|
+ rpcrdma_conn_func(&r_xprt->rx_ep);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+
|
|
|
+out_shortreply:
|
|
|
+ dprintk("RPC: %s: short/invalid reply\n", __func__);
|
|
|
+ goto repost;
|
|
|
+
|
|
|
+out_badversion:
|
|
|
+ dprintk("RPC: %s: invalid version %d\n",
|
|
|
+ __func__, be32_to_cpu(headerp->rm_vers));
|
|
|
+ goto repost;
|
|
|
+
|
|
|
+out_nomatch:
|
|
|
+ spin_unlock(&xprt->transport_lock);
|
|
|
+ dprintk("RPC: %s: no match for incoming xid 0x%08x len %d\n",
|
|
|
+ __func__, be32_to_cpu(headerp->rm_xid),
|
|
|
+ rep->rr_len);
|
|
|
+ goto repost;
|
|
|
+
|
|
|
+out_duplicate:
|
|
|
spin_unlock(&xprt->transport_lock);
|
|
|
+ dprintk("RPC: %s: "
|
|
|
+ "duplicate reply %p to RPC request %p: xid 0x%08x\n",
|
|
|
+ __func__, rep, req, be32_to_cpu(headerp->rm_xid));
|
|
|
+
|
|
|
+repost:
|
|
|
+ r_xprt->rx_stats.bad_reply_count++;
|
|
|
+ if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, &r_xprt->rx_ep, rep))
|
|
|
+ rpcrdma_recv_buffer_put(rep);
|
|
|
}
|