Commit 8a053433 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent e4b52ca0
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -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);
	rpcrdma_complete_rqst(rep);

	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);
}

/**
@@ -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);
}
+29 −3
Original line number Diff line number Diff line
@@ -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)
{
+1 −0
Original line number Diff line number Diff line
@@ -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)