xprtrdma: Do not wake RPC consumer on a failed LocalInv
Throw away any reply where the LocalInv flushes or could not be posted. The registered memory region is in an unknown state until the disconnect completes. rpcrdma_xprt_disconnect() will find and release the MR. No need to put it back on the MR free list in this case. The client retransmits pending RPC requests once it reestablishes a fresh connection, so a replacement reply should be forthcoming on the next connection instance. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
Родитель
e4b52ca013
Коммит
8a053433de
|
@ -576,10 +576,14 @@ static void frwr_wc_localinv_done(struct ib_cq *cq, struct ib_wc *wc)
|
|||
rep = mr->mr_req->rl_reply;
|
||||
smp_rmb();
|
||||
|
||||
frwr_mr_done(wc, mr);
|
||||
if (wc->status != IB_WC_SUCCESS) {
|
||||
if (rep)
|
||||
rpcrdma_unpin_rqst(rep);
|
||||
rpcrdma_flush_disconnect(cq->cq_context, wc);
|
||||
return;
|
||||
}
|
||||
frwr_mr_put(mr);
|
||||
rpcrdma_complete_rqst(rep);
|
||||
|
||||
rpcrdma_flush_disconnect(cq->cq_context, wc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -645,8 +649,9 @@ void frwr_unmap_async(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
|
|||
trace_xprtrdma_post_linv_err(req, rc);
|
||||
|
||||
/* The final LOCAL_INV WR in the chain is supposed to
|
||||
* do the wake. If it was never posted, the wake will
|
||||
* not happen, so wake here in that case.
|
||||
* do the wake. If it was never posted, the wake does
|
||||
* not happen. Unpin the rqst in preparation for its
|
||||
* retransmission.
|
||||
*/
|
||||
rpcrdma_complete_rqst(req->rl_reply);
|
||||
rpcrdma_unpin_rqst(req->rl_reply);
|
||||
}
|
||||
|
|
|
@ -1326,9 +1326,35 @@ rpcrdma_decode_error(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* Perform XID lookup, reconstruction of the RPC reply, and
|
||||
* RPC completion while holding the transport lock to ensure
|
||||
* the rep, rqst, and rq_task pointers remain stable.
|
||||
/**
|
||||
* rpcrdma_unpin_rqst - Release rqst without completing it
|
||||
* @rep: RPC/RDMA Receive context
|
||||
*
|
||||
* This is done when a connection is lost so that a Reply
|
||||
* can be dropped and its matching Call can be subsequently
|
||||
* retransmitted on a new connection.
|
||||
*/
|
||||
void rpcrdma_unpin_rqst(struct rpcrdma_rep *rep)
|
||||
{
|
||||
struct rpc_xprt *xprt = &rep->rr_rxprt->rx_xprt;
|
||||
struct rpc_rqst *rqst = rep->rr_rqst;
|
||||
struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
|
||||
|
||||
req->rl_reply = NULL;
|
||||
rep->rr_rqst = NULL;
|
||||
|
||||
spin_lock(&xprt->queue_lock);
|
||||
xprt_unpin_rqst(rqst);
|
||||
spin_unlock(&xprt->queue_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpcrdma_complete_rqst - Pass completed rqst back to RPC
|
||||
* @rep: RPC/RDMA Receive context
|
||||
*
|
||||
* Reconstruct the RPC reply and complete the transaction
|
||||
* while @rqst is still pinned to ensure the rep, rqst, and
|
||||
* rq_task pointers remain stable.
|
||||
*/
|
||||
void rpcrdma_complete_rqst(struct rpcrdma_rep *rep)
|
||||
{
|
||||
|
|
|
@ -561,6 +561,7 @@ int rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst);
|
|||
void rpcrdma_set_max_header_sizes(struct rpcrdma_ep *ep);
|
||||
void rpcrdma_reset_cwnd(struct rpcrdma_xprt *r_xprt);
|
||||
void rpcrdma_complete_rqst(struct rpcrdma_rep *rep);
|
||||
void rpcrdma_unpin_rqst(struct rpcrdma_rep *rep);
|
||||
void rpcrdma_reply_handler(struct rpcrdma_rep *rep);
|
||||
|
||||
static inline void rpcrdma_set_xdrlen(struct xdr_buf *xdr, size_t len)
|
||||
|
|
Загрузка…
Ссылка в новой задаче