diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2016-06-29 13:52:21 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-07-11 15:50:43 -0400 |
commit | 564471d2f2f1ddaf02119b8759813666db93abba (patch) | |
tree | 9c619e238fe4e31a7135e8f9a694640df5b8e5e2 | |
parent | 38f1932e60ba249660bbae585f61ef2dee3313a4 (diff) |
xprtrdma: Create common scatterlist fields in rpcrdma_mw
Clean up: FMR is about to replace the rpcrdma_map_one code with
scatterlists. Move the scatterlist fields out of the FRWR-specific
union and into the generic part of rpcrdma_mw.
One minor change: -EIO is now returned if FRWR registration fails.
The RPC is terminated immediately, since the problem is likely due
to a software bug, thus retrying likely won't help.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | net/sunrpc/xprtrdma/frwr_ops.c | 85 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 8 |
2 files changed, 46 insertions, 47 deletions
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index c0947544babe..f02ab80aa6ee 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -125,17 +125,16 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r) | |||
125 | } | 125 | } |
126 | 126 | ||
127 | static void | 127 | static void |
128 | __frwr_reset_and_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mw *mw) | 128 | __frwr_reset_and_unmap(struct rpcrdma_mw *mw) |
129 | { | 129 | { |
130 | struct rpcrdma_xprt *r_xprt = mw->mw_xprt; | ||
130 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 131 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
131 | struct rpcrdma_frmr *f = &mw->frmr; | ||
132 | int rc; | 132 | int rc; |
133 | 133 | ||
134 | rc = __frwr_reset_mr(ia, mw); | 134 | rc = __frwr_reset_mr(ia, mw); |
135 | ib_dma_unmap_sg(ia->ri_device, f->fr_sg, f->fr_nents, f->fr_dir); | 135 | ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir); |
136 | if (rc) | 136 | if (rc) |
137 | return; | 137 | return; |
138 | |||
139 | rpcrdma_put_mw(r_xprt, mw); | 138 | rpcrdma_put_mw(r_xprt, mw); |
140 | } | 139 | } |
141 | 140 | ||
@@ -152,8 +151,7 @@ __frwr_recovery_worker(struct work_struct *work) | |||
152 | struct rpcrdma_mw *r = container_of(work, struct rpcrdma_mw, | 151 | struct rpcrdma_mw *r = container_of(work, struct rpcrdma_mw, |
153 | mw_work); | 152 | mw_work); |
154 | 153 | ||
155 | __frwr_reset_and_unmap(r->mw_xprt, r); | 154 | __frwr_reset_and_unmap(r); |
156 | return; | ||
157 | } | 155 | } |
158 | 156 | ||
159 | /* A broken MR was discovered in a context that can't sleep. | 157 | /* A broken MR was discovered in a context that can't sleep. |
@@ -167,8 +165,7 @@ __frwr_queue_recovery(struct rpcrdma_mw *r) | |||
167 | } | 165 | } |
168 | 166 | ||
169 | static int | 167 | static int |
170 | __frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, struct ib_device *device, | 168 | __frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, unsigned int depth) |
171 | unsigned int depth) | ||
172 | { | 169 | { |
173 | struct rpcrdma_frmr *f = &r->frmr; | 170 | struct rpcrdma_frmr *f = &r->frmr; |
174 | int rc; | 171 | int rc; |
@@ -177,11 +174,11 @@ __frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, struct ib_device *device, | |||
177 | if (IS_ERR(f->fr_mr)) | 174 | if (IS_ERR(f->fr_mr)) |
178 | goto out_mr_err; | 175 | goto out_mr_err; |
179 | 176 | ||
180 | f->fr_sg = kcalloc(depth, sizeof(*f->fr_sg), GFP_KERNEL); | 177 | r->mw_sg = kcalloc(depth, sizeof(*r->mw_sg), GFP_KERNEL); |
181 | if (!f->fr_sg) | 178 | if (!r->mw_sg) |
182 | goto out_list_err; | 179 | goto out_list_err; |
183 | 180 | ||
184 | sg_init_table(f->fr_sg, depth); | 181 | sg_init_table(r->mw_sg, depth); |
185 | 182 | ||
186 | init_completion(&f->fr_linv_done); | 183 | init_completion(&f->fr_linv_done); |
187 | 184 | ||
@@ -210,7 +207,7 @@ __frwr_release(struct rpcrdma_mw *r) | |||
210 | if (rc) | 207 | if (rc) |
211 | dprintk("RPC: %s: ib_dereg_mr status %i\n", | 208 | dprintk("RPC: %s: ib_dereg_mr status %i\n", |
212 | __func__, rc); | 209 | __func__, rc); |
213 | kfree(r->frmr.fr_sg); | 210 | kfree(r->mw_sg); |
214 | } | 211 | } |
215 | 212 | ||
216 | static int | 213 | static int |
@@ -350,7 +347,6 @@ static int | |||
350 | frwr_op_init(struct rpcrdma_xprt *r_xprt) | 347 | frwr_op_init(struct rpcrdma_xprt *r_xprt) |
351 | { | 348 | { |
352 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | 349 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; |
353 | struct ib_device *device = r_xprt->rx_ia.ri_device; | ||
354 | unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth; | 350 | unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth; |
355 | struct ib_pd *pd = r_xprt->rx_ia.ri_pd; | 351 | struct ib_pd *pd = r_xprt->rx_ia.ri_pd; |
356 | int i; | 352 | int i; |
@@ -372,7 +368,7 @@ frwr_op_init(struct rpcrdma_xprt *r_xprt) | |||
372 | if (!r) | 368 | if (!r) |
373 | return -ENOMEM; | 369 | return -ENOMEM; |
374 | 370 | ||
375 | rc = __frwr_init(r, pd, device, depth); | 371 | rc = __frwr_init(r, pd, depth); |
376 | if (rc) { | 372 | if (rc) { |
377 | kfree(r); | 373 | kfree(r); |
378 | return rc; | 374 | return rc; |
@@ -386,7 +382,7 @@ frwr_op_init(struct rpcrdma_xprt *r_xprt) | |||
386 | return 0; | 382 | return 0; |
387 | } | 383 | } |
388 | 384 | ||
389 | /* Post a FAST_REG Work Request to register a memory region | 385 | /* Post a REG_MR Work Request to register a memory region |
390 | * for remote access via RDMA READ or RDMA WRITE. | 386 | * for remote access via RDMA READ or RDMA WRITE. |
391 | */ | 387 | */ |
392 | static int | 388 | static int |
@@ -394,8 +390,6 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, | |||
394 | int nsegs, bool writing) | 390 | int nsegs, bool writing) |
395 | { | 391 | { |
396 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 392 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
397 | struct ib_device *device = ia->ri_device; | ||
398 | enum dma_data_direction direction = rpcrdma_data_dir(writing); | ||
399 | struct rpcrdma_mr_seg *seg1 = seg; | 393 | struct rpcrdma_mr_seg *seg1 = seg; |
400 | struct rpcrdma_mw *mw; | 394 | struct rpcrdma_mw *mw; |
401 | struct rpcrdma_frmr *frmr; | 395 | struct rpcrdma_frmr *frmr; |
@@ -421,15 +415,14 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, | |||
421 | 415 | ||
422 | if (nsegs > ia->ri_max_frmr_depth) | 416 | if (nsegs > ia->ri_max_frmr_depth) |
423 | nsegs = ia->ri_max_frmr_depth; | 417 | nsegs = ia->ri_max_frmr_depth; |
424 | |||
425 | for (i = 0; i < nsegs;) { | 418 | for (i = 0; i < nsegs;) { |
426 | if (seg->mr_page) | 419 | if (seg->mr_page) |
427 | sg_set_page(&frmr->fr_sg[i], | 420 | sg_set_page(&mw->mw_sg[i], |
428 | seg->mr_page, | 421 | seg->mr_page, |
429 | seg->mr_len, | 422 | seg->mr_len, |
430 | offset_in_page(seg->mr_offset)); | 423 | offset_in_page(seg->mr_offset)); |
431 | else | 424 | else |
432 | sg_set_buf(&frmr->fr_sg[i], seg->mr_offset, | 425 | sg_set_buf(&mw->mw_sg[i], seg->mr_offset, |
433 | seg->mr_len); | 426 | seg->mr_len); |
434 | 427 | ||
435 | ++seg; | 428 | ++seg; |
@@ -440,26 +433,20 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, | |||
440 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) | 433 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) |
441 | break; | 434 | break; |
442 | } | 435 | } |
443 | frmr->fr_nents = i; | 436 | mw->mw_nents = i; |
444 | frmr->fr_dir = direction; | 437 | mw->mw_dir = rpcrdma_data_dir(writing); |
445 | |||
446 | dma_nents = ib_dma_map_sg(device, frmr->fr_sg, frmr->fr_nents, direction); | ||
447 | if (!dma_nents) { | ||
448 | pr_err("RPC: %s: failed to dma map sg %p sg_nents %u\n", | ||
449 | __func__, frmr->fr_sg, frmr->fr_nents); | ||
450 | return -ENOMEM; | ||
451 | } | ||
452 | 438 | ||
453 | n = ib_map_mr_sg(mr, frmr->fr_sg, frmr->fr_nents, NULL, PAGE_SIZE); | 439 | dma_nents = ib_dma_map_sg(ia->ri_device, |
454 | if (unlikely(n != frmr->fr_nents)) { | 440 | mw->mw_sg, mw->mw_nents, mw->mw_dir); |
455 | pr_err("RPC: %s: failed to map mr %p (%u/%u)\n", | 441 | if (!dma_nents) |
456 | __func__, frmr->fr_mr, n, frmr->fr_nents); | 442 | goto out_dmamap_err; |
457 | rc = n < 0 ? n : -EINVAL; | 443 | |
458 | goto out_senderr; | 444 | n = ib_map_mr_sg(mr, mw->mw_sg, mw->mw_nents, NULL, PAGE_SIZE); |
459 | } | 445 | if (unlikely(n != mw->mw_nents)) |
446 | goto out_mapmr_err; | ||
460 | 447 | ||
461 | dprintk("RPC: %s: Using frmr %p to map %u segments (%u bytes)\n", | 448 | dprintk("RPC: %s: Using frmr %p to map %u segments (%u bytes)\n", |
462 | __func__, mw, frmr->fr_nents, mr->length); | 449 | __func__, mw, mw->mw_nents, mr->length); |
463 | 450 | ||
464 | key = (u8)(mr->rkey & 0x000000FF); | 451 | key = (u8)(mr->rkey & 0x000000FF); |
465 | ib_update_fast_reg_key(mr, ++key); | 452 | ib_update_fast_reg_key(mr, ++key); |
@@ -484,13 +471,25 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, | |||
484 | seg1->rl_mw = mw; | 471 | seg1->rl_mw = mw; |
485 | seg1->mr_rkey = mr->rkey; | 472 | seg1->mr_rkey = mr->rkey; |
486 | seg1->mr_base = mr->iova; | 473 | seg1->mr_base = mr->iova; |
487 | seg1->mr_nsegs = frmr->fr_nents; | 474 | seg1->mr_nsegs = mw->mw_nents; |
488 | seg1->mr_len = mr->length; | 475 | seg1->mr_len = mr->length; |
489 | 476 | ||
490 | return frmr->fr_nents; | 477 | return mw->mw_nents; |
478 | |||
479 | out_dmamap_err: | ||
480 | pr_err("rpcrdma: failed to dma map sg %p sg_nents %u\n", | ||
481 | mw->mw_sg, mw->mw_nents); | ||
482 | return -ENOMEM; | ||
483 | |||
484 | out_mapmr_err: | ||
485 | pr_err("rpcrdma: failed to map mr %p (%u/%u)\n", | ||
486 | frmr->fr_mr, n, mw->mw_nents); | ||
487 | rc = n < 0 ? n : -EIO; | ||
488 | __frwr_queue_recovery(mw); | ||
489 | return rc; | ||
491 | 490 | ||
492 | out_senderr: | 491 | out_senderr: |
493 | dprintk("RPC: %s: ib_post_send status %i\n", __func__, rc); | 492 | pr_err("rpcrdma: ib_post_send status %i\n", rc); |
494 | __frwr_queue_recovery(mw); | 493 | __frwr_queue_recovery(mw); |
495 | return rc; | 494 | return rc; |
496 | } | 495 | } |
@@ -582,8 +581,8 @@ unmap: | |||
582 | mw = seg->rl_mw; | 581 | mw = seg->rl_mw; |
583 | seg->rl_mw = NULL; | 582 | seg->rl_mw = NULL; |
584 | 583 | ||
585 | ib_dma_unmap_sg(ia->ri_device, f->fr_sg, f->fr_nents, | 584 | ib_dma_unmap_sg(ia->ri_device, |
586 | f->fr_dir); | 585 | mw->mw_sg, mw->mw_nents, mw->mw_dir); |
587 | rpcrdma_put_mw(r_xprt, mw); | 586 | rpcrdma_put_mw(r_xprt, mw); |
588 | 587 | ||
589 | i += seg->mr_nsegs; | 588 | i += seg->mr_nsegs; |
@@ -630,7 +629,7 @@ frwr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, | |||
630 | mw = seg->rl_mw; | 629 | mw = seg->rl_mw; |
631 | 630 | ||
632 | if (sync) | 631 | if (sync) |
633 | __frwr_reset_and_unmap(r_xprt, mw); | 632 | __frwr_reset_and_unmap(mw); |
634 | else | 633 | else |
635 | __frwr_queue_recovery(mw); | 634 | __frwr_queue_recovery(mw); |
636 | 635 | ||
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 95cdc66225ee..c53abd1281b3 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -221,9 +221,6 @@ enum rpcrdma_frmr_state { | |||
221 | }; | 221 | }; |
222 | 222 | ||
223 | struct rpcrdma_frmr { | 223 | struct rpcrdma_frmr { |
224 | struct scatterlist *fr_sg; | ||
225 | int fr_nents; | ||
226 | enum dma_data_direction fr_dir; | ||
227 | struct ib_mr *fr_mr; | 224 | struct ib_mr *fr_mr; |
228 | struct ib_cqe fr_cqe; | 225 | struct ib_cqe fr_cqe; |
229 | enum rpcrdma_frmr_state fr_state; | 226 | enum rpcrdma_frmr_state fr_state; |
@@ -240,13 +237,16 @@ struct rpcrdma_fmr { | |||
240 | }; | 237 | }; |
241 | 238 | ||
242 | struct rpcrdma_mw { | 239 | struct rpcrdma_mw { |
240 | struct list_head mw_list; | ||
241 | struct scatterlist *mw_sg; | ||
242 | int mw_nents; | ||
243 | enum dma_data_direction mw_dir; | ||
243 | union { | 244 | union { |
244 | struct rpcrdma_fmr fmr; | 245 | struct rpcrdma_fmr fmr; |
245 | struct rpcrdma_frmr frmr; | 246 | struct rpcrdma_frmr frmr; |
246 | }; | 247 | }; |
247 | struct work_struct mw_work; | 248 | struct work_struct mw_work; |
248 | struct rpcrdma_xprt *mw_xprt; | 249 | struct rpcrdma_xprt *mw_xprt; |
249 | struct list_head mw_list; | ||
250 | struct list_head mw_all; | 250 | struct list_head mw_all; |
251 | }; | 251 | }; |
252 | 252 | ||