aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sunrpc/xprtrdma/fmr_ops.c23
-rw-r--r--net/sunrpc/xprtrdma/frwr_ops.c51
-rw-r--r--net/sunrpc/xprtrdma/physical_ops.c6
-rw-r--r--net/sunrpc/xprtrdma/verbs.c103
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h1
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 */
154static void
155fmr_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
149const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = { 171const 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
49static 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 */
235static void
236frwr_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
213const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = { 263const 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
62static void
63physical_op_reset(struct rpcrdma_xprt *r_xprt)
64{
65}
66
62const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops = { 67const 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
66static void rpcrdma_reset_frmrs(struct rpcrdma_ia *);
67static 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 */
1297static void
1298rpcrdma_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 */
1330static void
1331rpcrdma_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