diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2014-11-08 20:14:29 -0500 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2014-11-25 13:39:20 -0500 |
commit | 467c9674bccc073684ee34f4bd205cf1b135d76e (patch) | |
tree | cefc907944bb2dcbefec1a7fbf7a4a2df1e775da /net/sunrpc/xprtrdma | |
parent | e7104a2a96069975d489c60a30564372c6273a85 (diff) |
xprtrdma: unmap all FMRs during transport disconnect
When using RPCRDMA_MTHCAFMR memory registration, after a few
transport disconnect / reconnect cycles, ib_map_phys_fmr() starts to
return EINVAL because the provider has exhausted its map pool.
Make sure that all FMRs are unmapped during transport disconnect,
and that ->send_request remarshals them during an RPC retransmit.
This resets the transport's MRs to ensure that none are leaked
during a disconnect.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net/sunrpc/xprtrdma')
-rw-r--r-- | net/sunrpc/xprtrdma/transport.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 42 |
2 files changed, 42 insertions, 2 deletions
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 6a4615dd0261..cfe9a810e6bc 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -599,7 +599,7 @@ xprt_rdma_send_request(struct rpc_task *task) | |||
599 | 599 | ||
600 | if (req->rl_niovs == 0) | 600 | if (req->rl_niovs == 0) |
601 | rc = rpcrdma_marshal_req(rqst); | 601 | rc = rpcrdma_marshal_req(rqst); |
602 | else if (r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_FRMR) | 602 | else if (r_xprt->rx_ia.ri_memreg_strategy != RPCRDMA_ALLPHYSICAL) |
603 | rc = rpcrdma_marshal_chunks(rqst, 0); | 603 | rc = rpcrdma_marshal_chunks(rqst, 0); |
604 | if (rc < 0) | 604 | if (rc < 0) |
605 | goto failed_marshal; | 605 | goto failed_marshal; |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index af45cf390126..3c88276090e3 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | static void rpcrdma_reset_frmrs(struct rpcrdma_ia *); | 64 | static void rpcrdma_reset_frmrs(struct rpcrdma_ia *); |
65 | static void rpcrdma_reset_fmrs(struct rpcrdma_ia *); | ||
65 | 66 | ||
66 | /* | 67 | /* |
67 | * internal functions | 68 | * internal functions |
@@ -868,8 +869,19 @@ retry: | |||
868 | rpcrdma_ep_disconnect(ep, ia); | 869 | rpcrdma_ep_disconnect(ep, ia); |
869 | rpcrdma_flush_cqs(ep); | 870 | rpcrdma_flush_cqs(ep); |
870 | 871 | ||
871 | if (ia->ri_memreg_strategy == RPCRDMA_FRMR) | 872 | switch (ia->ri_memreg_strategy) { |
873 | case RPCRDMA_FRMR: | ||
872 | rpcrdma_reset_frmrs(ia); | 874 | rpcrdma_reset_frmrs(ia); |
875 | break; | ||
876 | case RPCRDMA_MTHCAFMR: | ||
877 | rpcrdma_reset_fmrs(ia); | ||
878 | break; | ||
879 | case RPCRDMA_ALLPHYSICAL: | ||
880 | break; | ||
881 | default: | ||
882 | rc = -EIO; | ||
883 | goto out; | ||
884 | } | ||
873 | 885 | ||
874 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); | 886 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); |
875 | id = rpcrdma_create_id(xprt, ia, | 887 | id = rpcrdma_create_id(xprt, ia, |
@@ -1289,6 +1301,34 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | |||
1289 | kfree(buf->rb_pool); | 1301 | kfree(buf->rb_pool); |
1290 | } | 1302 | } |
1291 | 1303 | ||
1304 | /* After a disconnect, unmap all FMRs. | ||
1305 | * | ||
1306 | * This is invoked only in the transport connect worker in order | ||
1307 | * to serialize with rpcrdma_register_fmr_external(). | ||
1308 | */ | ||
1309 | static void | ||
1310 | rpcrdma_reset_fmrs(struct rpcrdma_ia *ia) | ||
1311 | { | ||
1312 | struct rpcrdma_xprt *r_xprt = | ||
1313 | container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
1314 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
1315 | struct list_head *pos; | ||
1316 | struct rpcrdma_mw *r; | ||
1317 | LIST_HEAD(l); | ||
1318 | int rc; | ||
1319 | |||
1320 | list_for_each(pos, &buf->rb_all) { | ||
1321 | r = list_entry(pos, struct rpcrdma_mw, mw_all); | ||
1322 | |||
1323 | INIT_LIST_HEAD(&l); | ||
1324 | list_add(&r->r.fmr->list, &l); | ||
1325 | rc = ib_unmap_fmr(&l); | ||
1326 | if (rc) | ||
1327 | dprintk("RPC: %s: ib_unmap_fmr failed %i\n", | ||
1328 | __func__, rc); | ||
1329 | } | ||
1330 | } | ||
1331 | |||
1292 | /* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in | 1332 | /* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in |
1293 | * an unusable state. Find FRMRs in this state and dereg / reg | 1333 | * an unusable state. Find FRMRs in this state and dereg / reg |
1294 | * each. FRMRs that are VALID and attached to an rpcrdma_req are | 1334 | * each. FRMRs that are VALID and attached to an rpcrdma_req are |