Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xprtrdma: Fix rpcrdma_reqs_reset()

Avoid FastReg operations getting MW_BIND_ERR after a reconnect.

rpcrdma_reqs_reset() is called on transport tear-down to get each
rpcrdma_req back into a clean state.

MRs on req->rl_registered are waiting for a FastReg, are already
registered, or are waiting for invalidation. If the transport is
being torn down when reqs_reset() is called, the matching LocalInv
might never be posted. That leaves these MR registered /and/ on
req->rl_free_mrs, where they can be re-used for the next
connection.

Since xprtrdma does not keep specific track of the MR state, it's
not possible to know what state these MRs are in, so the only safe
thing to do is release them immediately.

Fixes: 5de55ce951a1 ("xprtrdma: Release in-flight MRs on disconnect")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Chuck Lever and committed by
Anna Schumaker
acd9f2dd 49b29a57

+17 -2
+2 -1
net/sunrpc/xprtrdma/frwr_ops.c
··· 92 92 rpcrdma_mr_push(mr, &mr->mr_req->rl_free_mrs); 93 93 } 94 94 95 - /* frwr_reset - Place MRs back on the free list 95 + /** 96 + * frwr_reset - Place MRs back on @req's free list 96 97 * @req: request to reset 97 98 * 98 99 * Used after a failed marshal. For FRWR, this means the MRs
+15 -1
net/sunrpc/xprtrdma/verbs.c
··· 897 897 898 898 static void rpcrdma_req_reset(struct rpcrdma_req *req) 899 899 { 900 + struct rpcrdma_mr *mr; 901 + 900 902 /* Credits are valid for only one connection */ 901 903 req->rl_slot.rq_cong = 0; 902 904 ··· 908 906 rpcrdma_regbuf_dma_unmap(req->rl_sendbuf); 909 907 rpcrdma_regbuf_dma_unmap(req->rl_recvbuf); 910 908 911 - frwr_reset(req); 909 + /* The verbs consumer can't know the state of an MR on the 910 + * req->rl_registered list unless a successful completion 911 + * has occurred, so they cannot be re-used. 912 + */ 913 + while ((mr = rpcrdma_mr_pop(&req->rl_registered))) { 914 + struct rpcrdma_buffer *buf = &mr->mr_xprt->rx_buf; 915 + 916 + spin_lock(&buf->rb_lock); 917 + list_del(&mr->mr_all); 918 + spin_unlock(&buf->rb_lock); 919 + 920 + frwr_mr_release(mr); 921 + } 912 922 } 913 923 914 924 /* ASSUMPTION: the rb_allreqs list is stable for the duration,