mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
xprtrdma: Clear receive-side ownership pointers on release
Three small ownership-state cleanups land the transport in a state that lets future reviewers reason about each pointer locally rather than tracing the whole reply path: rpcrdma_rep_put() clears rep->rr_rqst before the rep enters rb_free_reps so that no rep on the free list still carries a stale rqst pointer. rpcrdma_reply_handler() and rpcrdma_unpin_rqst() are the only sites that set rr_rqst; rpcrdma_reply_handler() hands the rep through rpcrdma_rep_put(), and rpcrdma_unpin_rqst() NULLs rr_rqst directly because its error path abandons the rep for teardown cleanup rather than returning it to rb_free_reps. rpcrdma_reply_put() NULLs req->rl_reply before calling rpcrdma_rep_put(). The previous order placed the rep on rb_free_reps while req->rl_reply still pointed at it; the window was harmless because xprt_rdma_free_slot() holds the req exclusively across the pair, but closing it makes the invariant 'rep on rb_free_reps implies no req references it' strictly checkable. rpcrdma_sendctx_unmap() and rpcrdma_sendctx_cancel() clear req->rl_sendctx after dropping the sendctx pointer in the sendctx ring. Without this, req->rl_sendctx survives across Send completion and points at a sendctx that may already have been reassigned by rpcrdma_sendctx_get_locked() to a different req. No caller dereferences the stale pointer today -- rpcrdma_prepare_send_sges() overwrites it before the next Send -- but a NULL is a more honest representation of 'the Send is no longer outstanding' and lets the assertion patch that follows trip on any future regression. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
This commit is contained in:
parent
64bf689205
commit
2ae8e7afbc
|
|
@ -493,6 +493,7 @@ void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
|
|||
|
||||
rpcrdma_sendctx_dma_unmap(sc);
|
||||
sc->sc_req = NULL;
|
||||
req->rl_sendctx = NULL;
|
||||
rpcrdma_req_put(req);
|
||||
}
|
||||
|
||||
|
|
@ -501,8 +502,11 @@ void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
|
|||
*/
|
||||
static void rpcrdma_sendctx_cancel(struct rpcrdma_sendctx *sc)
|
||||
{
|
||||
struct rpcrdma_req *req = sc->sc_req;
|
||||
|
||||
rpcrdma_sendctx_dma_unmap(sc);
|
||||
sc->sc_req = NULL;
|
||||
req->rl_sendctx = NULL;
|
||||
}
|
||||
|
||||
/* Prepare an SGE for the RPC-over-RDMA transport header.
|
||||
|
|
|
|||
|
|
@ -1043,9 +1043,15 @@ static struct rpcrdma_rep *rpcrdma_rep_get_locked(struct rpcrdma_buffer *buf)
|
|||
* @buf: buffer pool
|
||||
* @rep: rep to release
|
||||
*
|
||||
* The rep's transient association with an rpc_rqst, established
|
||||
* by rpcrdma_reply_handler() and torn down here, must not survive
|
||||
* onto rb_free_reps: rpcrdma_post_recvs() pulls reps from the free
|
||||
* list to re-post them, and a non-NULL rr_rqst on a free-listed rep
|
||||
* would imply the rep is still referenced by a req.
|
||||
*/
|
||||
void rpcrdma_rep_put(struct rpcrdma_buffer *buf, struct rpcrdma_rep *rep)
|
||||
{
|
||||
rep->rr_rqst = NULL;
|
||||
llist_add(&rep->rr_node, &buf->rb_free_reps);
|
||||
}
|
||||
|
||||
|
|
@ -1247,9 +1253,11 @@ rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt)
|
|||
*/
|
||||
void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
|
||||
{
|
||||
if (req->rl_reply) {
|
||||
rpcrdma_rep_put(buffers, req->rl_reply);
|
||||
struct rpcrdma_rep *rep = req->rl_reply;
|
||||
|
||||
if (rep) {
|
||||
req->rl_reply = NULL;
|
||||
rpcrdma_rep_put(buffers, rep);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user