diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2015-03-30 14:35:07 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2015-03-31 09:52:53 -0400 |
commit | 31a701a94751509bb72e13d851f18ddcf22ff722 (patch) | |
tree | 679ccf7b79a187a3258b1eea0c8f42eaafadd77b /net/sunrpc | |
parent | 91e70e70e47b3355bb0a8b3b196c93897dcdb440 (diff) |
xprtrdma: Add "reset MRs" memreg op
This method is invoked when a transport instance is about to be
reconnected. Each Memory Region object is reset to its initial
state.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Tested-by: Devesh Sharma <Devesh.Sharma@Emulex.Com>
Tested-by: Meghana Cheripady <Meghana.Cheripady@Emulex.Com>
Tested-by: Veeresh U. Kokatnur <veereshuk@chelsio.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/xprtrdma/fmr_ops.c | 23 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/frwr_ops.c | 51 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/physical_ops.c | 6 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 103 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 1 |
5 files changed, 83 insertions, 101 deletions
diff --git a/net/sunrpc/xprtrdma/fmr_ops.c b/net/sunrpc/xprtrdma/fmr_ops.c index 825ce9641350..93261b05891e 100644 --- a/net/sunrpc/xprtrdma/fmr_ops.c +++ b/net/sunrpc/xprtrdma/fmr_ops.c | |||
@@ -146,10 +146,33 @@ out_err: | |||
146 | return nsegs; | 146 | return nsegs; |
147 | } | 147 | } |
148 | 148 | ||
149 | /* After a disconnect, unmap all FMRs. | ||
150 | * | ||
151 | * This is invoked only in the transport connect worker in order | ||
152 | * to serialize with rpcrdma_register_fmr_external(). | ||
153 | */ | ||
154 | static void | ||
155 | fmr_op_reset(struct rpcrdma_xprt *r_xprt) | ||
156 | { | ||
157 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
158 | struct rpcrdma_mw *r; | ||
159 | LIST_HEAD(list); | ||
160 | int rc; | ||
161 | |||
162 | list_for_each_entry(r, &buf->rb_all, mw_all) | ||
163 | list_add(&r->r.fmr->list, &list); | ||
164 | |||
165 | rc = ib_unmap_fmr(&list); | ||
166 | if (rc) | ||
167 | dprintk("RPC: %s: ib_unmap_fmr failed %i\n", | ||
168 | __func__, rc); | ||
169 | } | ||
170 | |||
149 | const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = { | 171 | const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = { |
150 | .ro_map = fmr_op_map, | 172 | .ro_map = fmr_op_map, |
151 | .ro_unmap = fmr_op_unmap, | 173 | .ro_unmap = fmr_op_unmap, |
152 | .ro_maxpages = fmr_op_maxpages, | 174 | .ro_maxpages = fmr_op_maxpages, |
153 | .ro_init = fmr_op_init, | 175 | .ro_init = fmr_op_init, |
176 | .ro_reset = fmr_op_reset, | ||
154 | .ro_displayname = "fmr", | 177 | .ro_displayname = "fmr", |
155 | }; | 178 | }; |
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 9168c15faafa..c2bb29d4df3c 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -46,6 +46,18 @@ out_list_err: | |||
46 | return rc; | 46 | return rc; |
47 | } | 47 | } |
48 | 48 | ||
49 | static void | ||
50 | __frwr_release(struct rpcrdma_mw *r) | ||
51 | { | ||
52 | int rc; | ||
53 | |||
54 | rc = ib_dereg_mr(r->r.frmr.fr_mr); | ||
55 | if (rc) | ||
56 | dprintk("RPC: %s: ib_dereg_mr status %i\n", | ||
57 | __func__, rc); | ||
58 | ib_free_fast_reg_page_list(r->r.frmr.fr_pgl); | ||
59 | } | ||
60 | |||
49 | /* FRWR mode conveys a list of pages per chunk segment. The | 61 | /* FRWR mode conveys a list of pages per chunk segment. The |
50 | * maximum length of that list is the FRWR page list depth. | 62 | * maximum length of that list is the FRWR page list depth. |
51 | */ | 63 | */ |
@@ -210,10 +222,49 @@ out_err: | |||
210 | return nsegs; | 222 | return nsegs; |
211 | } | 223 | } |
212 | 224 | ||
225 | /* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in | ||
226 | * an unusable state. Find FRMRs in this state and dereg / reg | ||
227 | * each. FRMRs that are VALID and attached to an rpcrdma_req are | ||
228 | * also torn down. | ||
229 | * | ||
230 | * This gives all in-use FRMRs a fresh rkey and leaves them INVALID. | ||
231 | * | ||
232 | * This is invoked only in the transport connect worker in order | ||
233 | * to serialize with rpcrdma_register_frmr_external(). | ||
234 | */ | ||
235 | static void | ||
236 | frwr_op_reset(struct rpcrdma_xprt *r_xprt) | ||
237 | { | ||
238 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
239 | struct ib_device *device = r_xprt->rx_ia.ri_id->device; | ||
240 | unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth; | ||
241 | struct ib_pd *pd = r_xprt->rx_ia.ri_pd; | ||
242 | struct rpcrdma_mw *r; | ||
243 | int rc; | ||
244 | |||
245 | list_for_each_entry(r, &buf->rb_all, mw_all) { | ||
246 | if (r->r.frmr.fr_state == FRMR_IS_INVALID) | ||
247 | continue; | ||
248 | |||
249 | __frwr_release(r); | ||
250 | rc = __frwr_init(r, pd, device, depth); | ||
251 | if (rc) { | ||
252 | dprintk("RPC: %s: mw %p left %s\n", | ||
253 | __func__, r, | ||
254 | (r->r.frmr.fr_state == FRMR_IS_STALE ? | ||
255 | "stale" : "valid")); | ||
256 | continue; | ||
257 | } | ||
258 | |||
259 | r->r.frmr.fr_state = FRMR_IS_INVALID; | ||
260 | } | ||
261 | } | ||
262 | |||
213 | const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = { | 263 | const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = { |
214 | .ro_map = frwr_op_map, | 264 | .ro_map = frwr_op_map, |
215 | .ro_unmap = frwr_op_unmap, | 265 | .ro_unmap = frwr_op_unmap, |
216 | .ro_maxpages = frwr_op_maxpages, | 266 | .ro_maxpages = frwr_op_maxpages, |
217 | .ro_init = frwr_op_init, | 267 | .ro_init = frwr_op_init, |
268 | .ro_reset = frwr_op_reset, | ||
218 | .ro_displayname = "frwr", | 269 | .ro_displayname = "frwr", |
219 | }; | 270 | }; |
diff --git a/net/sunrpc/xprtrdma/physical_ops.c b/net/sunrpc/xprtrdma/physical_ops.c index c37205190a2f..e0607136655b 100644 --- a/net/sunrpc/xprtrdma/physical_ops.c +++ b/net/sunrpc/xprtrdma/physical_ops.c | |||
@@ -59,10 +59,16 @@ physical_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg) | |||
59 | return 1; | 59 | return 1; |
60 | } | 60 | } |
61 | 61 | ||
62 | static void | ||
63 | physical_op_reset(struct rpcrdma_xprt *r_xprt) | ||
64 | { | ||
65 | } | ||
66 | |||
62 | const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops = { | 67 | const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops = { |
63 | .ro_map = physical_op_map, | 68 | .ro_map = physical_op_map, |
64 | .ro_unmap = physical_op_unmap, | 69 | .ro_unmap = physical_op_unmap, |
65 | .ro_maxpages = physical_op_maxpages, | 70 | .ro_maxpages = physical_op_maxpages, |
66 | .ro_init = physical_op_init, | 71 | .ro_init = physical_op_init, |
72 | .ro_reset = physical_op_reset, | ||
67 | .ro_displayname = "physical", | 73 | .ro_displayname = "physical", |
68 | }; | 74 | }; |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index e89a57d4e4f2..1b2c1f4ec4c3 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -63,9 +63,6 @@ | |||
63 | # define RPCDBG_FACILITY RPCDBG_TRANS | 63 | # define RPCDBG_FACILITY RPCDBG_TRANS |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | static void rpcrdma_reset_frmrs(struct rpcrdma_ia *); | ||
67 | static void rpcrdma_reset_fmrs(struct rpcrdma_ia *); | ||
68 | |||
69 | /* | 66 | /* |
70 | * internal functions | 67 | * internal functions |
71 | */ | 68 | */ |
@@ -945,21 +942,9 @@ retry: | |||
945 | rpcrdma_ep_disconnect(ep, ia); | 942 | rpcrdma_ep_disconnect(ep, ia); |
946 | rpcrdma_flush_cqs(ep); | 943 | rpcrdma_flush_cqs(ep); |
947 | 944 | ||
948 | switch (ia->ri_memreg_strategy) { | ||
949 | case RPCRDMA_FRMR: | ||
950 | rpcrdma_reset_frmrs(ia); | ||
951 | break; | ||
952 | case RPCRDMA_MTHCAFMR: | ||
953 | rpcrdma_reset_fmrs(ia); | ||
954 | break; | ||
955 | case RPCRDMA_ALLPHYSICAL: | ||
956 | break; | ||
957 | default: | ||
958 | rc = -EIO; | ||
959 | goto out; | ||
960 | } | ||
961 | |||
962 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); | 945 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); |
946 | ia->ri_ops->ro_reset(xprt); | ||
947 | |||
963 | id = rpcrdma_create_id(xprt, ia, | 948 | id = rpcrdma_create_id(xprt, ia, |
964 | (struct sockaddr *)&xprt->rx_data.addr); | 949 | (struct sockaddr *)&xprt->rx_data.addr); |
965 | if (IS_ERR(id)) { | 950 | if (IS_ERR(id)) { |
@@ -1289,90 +1274,6 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | |||
1289 | kfree(buf->rb_pool); | 1274 | kfree(buf->rb_pool); |
1290 | } | 1275 | } |
1291 | 1276 | ||
1292 | /* After a disconnect, unmap all FMRs. | ||
1293 | * | ||
1294 | * This is invoked only in the transport connect worker in order | ||
1295 | * to serialize with rpcrdma_register_fmr_external(). | ||
1296 | */ | ||
1297 | static void | ||
1298 | rpcrdma_reset_fmrs(struct rpcrdma_ia *ia) | ||
1299 | { | ||
1300 | struct rpcrdma_xprt *r_xprt = | ||
1301 | container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
1302 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
1303 | struct list_head *pos; | ||
1304 | struct rpcrdma_mw *r; | ||
1305 | LIST_HEAD(l); | ||
1306 | int rc; | ||
1307 | |||
1308 | list_for_each(pos, &buf->rb_all) { | ||
1309 | r = list_entry(pos, struct rpcrdma_mw, mw_all); | ||
1310 | |||
1311 | INIT_LIST_HEAD(&l); | ||
1312 | list_add(&r->r.fmr->list, &l); | ||
1313 | rc = ib_unmap_fmr(&l); | ||
1314 | if (rc) | ||
1315 | dprintk("RPC: %s: ib_unmap_fmr failed %i\n", | ||
1316 | __func__, rc); | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | /* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in | ||
1321 | * an unusable state. Find FRMRs in this state and dereg / reg | ||
1322 | * each. FRMRs that are VALID and attached to an rpcrdma_req are | ||
1323 | * also torn down. | ||
1324 | * | ||
1325 | * This gives all in-use FRMRs a fresh rkey and leaves them INVALID. | ||
1326 | * | ||
1327 | * This is invoked only in the transport connect worker in order | ||
1328 | * to serialize with rpcrdma_register_frmr_external(). | ||
1329 | */ | ||
1330 | static void | ||
1331 | rpcrdma_reset_frmrs(struct rpcrdma_ia *ia) | ||
1332 | { | ||
1333 | struct rpcrdma_xprt *r_xprt = | ||
1334 | container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
1335 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
1336 | struct list_head *pos; | ||
1337 | struct rpcrdma_mw *r; | ||
1338 | int rc; | ||
1339 | |||
1340 | list_for_each(pos, &buf->rb_all) { | ||
1341 | r = list_entry(pos, struct rpcrdma_mw, mw_all); | ||
1342 | |||
1343 | if (r->r.frmr.fr_state == FRMR_IS_INVALID) | ||
1344 | continue; | ||
1345 | |||
1346 | rc = ib_dereg_mr(r->r.frmr.fr_mr); | ||
1347 | if (rc) | ||
1348 | dprintk("RPC: %s: ib_dereg_mr failed %i\n", | ||
1349 | __func__, rc); | ||
1350 | ib_free_fast_reg_page_list(r->r.frmr.fr_pgl); | ||
1351 | |||
1352 | r->r.frmr.fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd, | ||
1353 | ia->ri_max_frmr_depth); | ||
1354 | if (IS_ERR(r->r.frmr.fr_mr)) { | ||
1355 | rc = PTR_ERR(r->r.frmr.fr_mr); | ||
1356 | dprintk("RPC: %s: ib_alloc_fast_reg_mr" | ||
1357 | " failed %i\n", __func__, rc); | ||
1358 | continue; | ||
1359 | } | ||
1360 | r->r.frmr.fr_pgl = ib_alloc_fast_reg_page_list( | ||
1361 | ia->ri_id->device, | ||
1362 | ia->ri_max_frmr_depth); | ||
1363 | if (IS_ERR(r->r.frmr.fr_pgl)) { | ||
1364 | rc = PTR_ERR(r->r.frmr.fr_pgl); | ||
1365 | dprintk("RPC: %s: " | ||
1366 | "ib_alloc_fast_reg_page_list " | ||
1367 | "failed %i\n", __func__, rc); | ||
1368 | |||
1369 | ib_dereg_mr(r->r.frmr.fr_mr); | ||
1370 | continue; | ||
1371 | } | ||
1372 | r->r.frmr.fr_state = FRMR_IS_INVALID; | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | /* "*mw" can be NULL when rpcrdma_buffer_get_mrs() fails, leaving | 1277 | /* "*mw" can be NULL when rpcrdma_buffer_get_mrs() fails, leaving |
1377 | * some req segments uninitialized. | 1278 | * some req segments uninitialized. |
1378 | */ | 1279 | */ |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 90b60feab45a..06802394cf89 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -342,6 +342,7 @@ struct rpcrdma_memreg_ops { | |||
342 | struct rpcrdma_mr_seg *); | 342 | struct rpcrdma_mr_seg *); |
343 | size_t (*ro_maxpages)(struct rpcrdma_xprt *); | 343 | size_t (*ro_maxpages)(struct rpcrdma_xprt *); |
344 | int (*ro_init)(struct rpcrdma_xprt *); | 344 | int (*ro_init)(struct rpcrdma_xprt *); |
345 | void (*ro_reset)(struct rpcrdma_xprt *); | ||
345 | const char *ro_displayname; | 346 | const char *ro_displayname; |
346 | }; | 347 | }; |
347 | 348 | ||