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 | ||
