Skip to content

Commit 73806c8

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Protect ia->ri_id when unmapping/invalidating MRs
Ensure ia->ri_id remains valid while invoking dma_unmap_page() or posting LOCAL_INV during a transport reconnect. Otherwise, ia->ri_id->device or ia->ri_id->qp is NULL, which triggers a panic. BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=259 Fixes: ec62f40 'xprtrdma: Ensure ia->ri_id->qp is not NULL when reconnecting' Signed-off-by: Chuck Lever <[email protected]> Tested-by: Steve Wise <[email protected]> Tested-by: Shirley Ma <[email protected]> Tested-by: Devesh Sharma <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 5fc83f4 commit 73806c8

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

net/sunrpc/xprtrdma/verbs.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
613613
/* Else will do memory reg/dereg for each chunk */
614614
ia->ri_memreg_strategy = memreg;
615615

616+
rwlock_init(&ia->ri_qplock);
616617
return 0;
617618
out2:
618619
rdma_destroy_id(ia->ri_id);
@@ -859,7 +860,7 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
859860
int
860861
rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
861862
{
862-
struct rdma_cm_id *id;
863+
struct rdma_cm_id *id, *old;
863864
int rc = 0;
864865
int retry_count = 0;
865866

@@ -905,9 +906,14 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
905906
rc = -ENETUNREACH;
906907
goto out;
907908
}
908-
rdma_destroy_qp(ia->ri_id);
909-
rdma_destroy_id(ia->ri_id);
909+
910+
write_lock(&ia->ri_qplock);
911+
old = ia->ri_id;
910912
ia->ri_id = id;
913+
write_unlock(&ia->ri_qplock);
914+
915+
rdma_destroy_qp(old);
916+
rdma_destroy_id(old);
911917
} else {
912918
dprintk("RPC: %s: connecting...\n", __func__);
913919
rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr);
@@ -1590,17 +1596,18 @@ rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg,
15901596
struct ib_send_wr invalidate_wr, *bad_wr;
15911597
int rc;
15921598

1593-
while (seg1->mr_nsegs--)
1594-
rpcrdma_unmap_one(ia, seg++);
1595-
15961599
memset(&invalidate_wr, 0, sizeof invalidate_wr);
15971600
invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw;
15981601
invalidate_wr.opcode = IB_WR_LOCAL_INV;
15991602
invalidate_wr.send_flags = IB_SEND_SIGNALED;
16001603
invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
16011604
DECR_CQCOUNT(&r_xprt->rx_ep);
16021605

1606+
read_lock(&ia->ri_qplock);
1607+
while (seg1->mr_nsegs--)
1608+
rpcrdma_unmap_one(ia, seg++);
16031609
rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr);
1610+
read_unlock(&ia->ri_qplock);
16041611
if (rc)
16051612
dprintk("RPC: %s: failed ib_post_send for invalidate,"
16061613
" status %i\n", __func__, rc);
@@ -1661,8 +1668,10 @@ rpcrdma_deregister_fmr_external(struct rpcrdma_mr_seg *seg,
16611668

16621669
list_add(&seg1->mr_chunk.rl_mw->r.fmr->list, &l);
16631670
rc = ib_unmap_fmr(&l);
1671+
read_lock(&ia->ri_qplock);
16641672
while (seg1->mr_nsegs--)
16651673
rpcrdma_unmap_one(ia, seg++);
1674+
read_unlock(&ia->ri_qplock);
16661675
if (rc)
16671676
dprintk("RPC: %s: failed ib_unmap_fmr,"
16681677
" status %i\n", __func__, rc);
@@ -1718,7 +1727,9 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg,
17181727

17191728
#if RPCRDMA_PERSISTENT_REGISTRATION
17201729
case RPCRDMA_ALLPHYSICAL:
1730+
read_lock(&ia->ri_qplock);
17211731
rpcrdma_unmap_one(ia, seg);
1732+
read_unlock(&ia->ri_qplock);
17221733
break;
17231734
#endif
17241735

net/sunrpc/xprtrdma/xprt_rdma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
* Interface Adapter -- one per transport instance
6060
*/
6161
struct rpcrdma_ia {
62+
rwlock_t ri_qplock;
6263
struct rdma_cm_id *ri_id;
6364
struct ib_pd *ri_pd;
6465
struct ib_mr *ri_bind_mem;

0 commit comments

Comments
 (0)