diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2019-08-19 18:45:37 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2019-08-20 16:23:35 -0400 |
commit | 3b39f52a02d4b3322744a0a32d59142e01afa435 (patch) | |
tree | e2380bbe235ecb137d22aa44d963bf4af15204e2 | |
parent | 1ca3f4c054a4e3765bdeb62c849d940b5bc8002d (diff) |
xprtrdma: Move rpcrdma_mr_get out of frwr_map
Refactor: Retrieve an MR and handle error recovery entirely in
rpc_rdma.c, as this is not a device-specific function.
Note that since commit 89f90fe1ad8b ("SUNRPC: Allow calls to
xprt_transmit() to drain the entire transmit queue"), the
xprt_transmit function handles the cond_resched. The transport no
longer has to do this itself.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | include/trace/events/rpcrdma.h | 29 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/frwr_ops.c | 23 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 30 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 21 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 4 |
5 files changed, 63 insertions, 44 deletions
diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h index 6e6055eb67e7..83c4dfd7feea 100644 --- a/include/trace/events/rpcrdma.h +++ b/include/trace/events/rpcrdma.h | |||
@@ -464,7 +464,34 @@ TRACE_EVENT(xprtrdma_createmrs, | |||
464 | ) | 464 | ) |
465 | ); | 465 | ); |
466 | 466 | ||
467 | DEFINE_RXPRT_EVENT(xprtrdma_nomrs); | 467 | TRACE_EVENT(xprtrdma_nomrs, |
468 | TP_PROTO( | ||
469 | const struct rpcrdma_req *req | ||
470 | ), | ||
471 | |||
472 | TP_ARGS(req), | ||
473 | |||
474 | TP_STRUCT__entry( | ||
475 | __field(const void *, req) | ||
476 | __field(unsigned int, task_id) | ||
477 | __field(unsigned int, client_id) | ||
478 | __field(u32, xid) | ||
479 | ), | ||
480 | |||
481 | TP_fast_assign( | ||
482 | const struct rpc_rqst *rqst = &req->rl_slot; | ||
483 | |||
484 | __entry->req = req; | ||
485 | __entry->task_id = rqst->rq_task->tk_pid; | ||
486 | __entry->client_id = rqst->rq_task->tk_client->cl_clid; | ||
487 | __entry->xid = be32_to_cpu(rqst->rq_xid); | ||
488 | ), | ||
489 | |||
490 | TP_printk("task:%u@%u xid=0x%08x req=%p", | ||
491 | __entry->task_id, __entry->client_id, __entry->xid, | ||
492 | __entry->req | ||
493 | ) | ||
494 | ); | ||
468 | 495 | ||
469 | DEFINE_RDCH_EVENT(read); | 496 | DEFINE_RDCH_EVENT(read); |
470 | DEFINE_WRCH_EVENT(write); | 497 | DEFINE_WRCH_EVENT(write); |
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 97e1804139b8..362056f4f48d 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c | |||
@@ -291,31 +291,25 @@ size_t frwr_maxpages(struct rpcrdma_xprt *r_xprt) | |||
291 | * @nsegs: number of segments remaining | 291 | * @nsegs: number of segments remaining |
292 | * @writing: true when RDMA Write will be used | 292 | * @writing: true when RDMA Write will be used |
293 | * @xid: XID of RPC using the registered memory | 293 | * @xid: XID of RPC using the registered memory |
294 | * @out: initialized MR | 294 | * @mr: MR to fill in |
295 | * | 295 | * |
296 | * Prepare a REG_MR Work Request to register a memory region | 296 | * Prepare a REG_MR Work Request to register a memory region |
297 | * for remote access via RDMA READ or RDMA WRITE. | 297 | * for remote access via RDMA READ or RDMA WRITE. |
298 | * | 298 | * |
299 | * Returns the next segment or a negative errno pointer. | 299 | * Returns the next segment or a negative errno pointer. |
300 | * On success, the prepared MR is planted in @out. | 300 | * On success, @mr is filled in. |
301 | */ | 301 | */ |
302 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | 302 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, |
303 | struct rpcrdma_mr_seg *seg, | 303 | struct rpcrdma_mr_seg *seg, |
304 | int nsegs, bool writing, __be32 xid, | 304 | int nsegs, bool writing, __be32 xid, |
305 | struct rpcrdma_mr **out) | 305 | struct rpcrdma_mr *mr) |
306 | { | 306 | { |
307 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | 307 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; |
308 | bool holes_ok = ia->ri_mrtype == IB_MR_TYPE_SG_GAPS; | ||
309 | struct rpcrdma_mr *mr; | ||
310 | struct ib_mr *ibmr; | ||
311 | struct ib_reg_wr *reg_wr; | 308 | struct ib_reg_wr *reg_wr; |
309 | struct ib_mr *ibmr; | ||
312 | int i, n; | 310 | int i, n; |
313 | u8 key; | 311 | u8 key; |
314 | 312 | ||
315 | mr = rpcrdma_mr_get(r_xprt); | ||
316 | if (!mr) | ||
317 | goto out_getmr_err; | ||
318 | |||
319 | if (nsegs > ia->ri_max_frwr_depth) | 313 | if (nsegs > ia->ri_max_frwr_depth) |
320 | nsegs = ia->ri_max_frwr_depth; | 314 | nsegs = ia->ri_max_frwr_depth; |
321 | for (i = 0; i < nsegs;) { | 315 | for (i = 0; i < nsegs;) { |
@@ -330,7 +324,7 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | |||
330 | 324 | ||
331 | ++seg; | 325 | ++seg; |
332 | ++i; | 326 | ++i; |
333 | if (holes_ok) | 327 | if (ia->ri_mrtype == IB_MR_TYPE_SG_GAPS) |
334 | continue; | 328 | continue; |
335 | if ((i < nsegs && offset_in_page(seg->mr_offset)) || | 329 | if ((i < nsegs && offset_in_page(seg->mr_offset)) || |
336 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) | 330 | offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) |
@@ -365,22 +359,15 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | |||
365 | mr->mr_offset = ibmr->iova; | 359 | mr->mr_offset = ibmr->iova; |
366 | trace_xprtrdma_mr_map(mr); | 360 | trace_xprtrdma_mr_map(mr); |
367 | 361 | ||
368 | *out = mr; | ||
369 | return seg; | 362 | return seg; |
370 | 363 | ||
371 | out_getmr_err: | ||
372 | xprt_wait_for_buffer_space(&r_xprt->rx_xprt); | ||
373 | return ERR_PTR(-EAGAIN); | ||
374 | |||
375 | out_dmamap_err: | 364 | out_dmamap_err: |
376 | mr->mr_dir = DMA_NONE; | 365 | mr->mr_dir = DMA_NONE; |
377 | trace_xprtrdma_frwr_sgerr(mr, i); | 366 | trace_xprtrdma_frwr_sgerr(mr, i); |
378 | rpcrdma_mr_put(mr); | ||
379 | return ERR_PTR(-EIO); | 367 | return ERR_PTR(-EIO); |
380 | 368 | ||
381 | out_mapmr_err: | 369 | out_mapmr_err: |
382 | trace_xprtrdma_frwr_maperr(mr, n); | 370 | trace_xprtrdma_frwr_maperr(mr, n); |
383 | rpcrdma_mr_recycle(mr); | ||
384 | return ERR_PTR(-EIO); | 371 | return ERR_PTR(-EIO); |
385 | } | 372 | } |
386 | 373 | ||
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 0ac096a6348a..34772cb19286 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -342,6 +342,27 @@ encode_read_segment(struct xdr_stream *xdr, struct rpcrdma_mr *mr, | |||
342 | return 0; | 342 | return 0; |
343 | } | 343 | } |
344 | 344 | ||
345 | static struct rpcrdma_mr_seg *rpcrdma_mr_prepare(struct rpcrdma_xprt *r_xprt, | ||
346 | struct rpcrdma_req *req, | ||
347 | struct rpcrdma_mr_seg *seg, | ||
348 | int nsegs, bool writing, | ||
349 | struct rpcrdma_mr **mr) | ||
350 | { | ||
351 | *mr = rpcrdma_mr_get(r_xprt); | ||
352 | if (!*mr) | ||
353 | goto out_getmr_err; | ||
354 | |||
355 | rpcrdma_mr_push(*mr, &req->rl_registered); | ||
356 | return frwr_map(r_xprt, seg, nsegs, writing, req->rl_slot.rq_xid, *mr); | ||
357 | |||
358 | out_getmr_err: | ||
359 | trace_xprtrdma_nomrs(req); | ||
360 | xprt_wait_for_buffer_space(&r_xprt->rx_xprt); | ||
361 | if (r_xprt->rx_ep.rep_connected != -ENODEV) | ||
362 | schedule_work(&r_xprt->rx_buf.rb_refresh_worker); | ||
363 | return ERR_PTR(-EAGAIN); | ||
364 | } | ||
365 | |||
345 | /* Register and XDR encode the Read list. Supports encoding a list of read | 366 | /* Register and XDR encode the Read list. Supports encoding a list of read |
346 | * segments that belong to a single read chunk. | 367 | * segments that belong to a single read chunk. |
347 | * | 368 | * |
@@ -379,10 +400,9 @@ rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, | |||
379 | return nsegs; | 400 | return nsegs; |
380 | 401 | ||
381 | do { | 402 | do { |
382 | seg = frwr_map(r_xprt, seg, nsegs, false, rqst->rq_xid, &mr); | 403 | seg = rpcrdma_mr_prepare(r_xprt, req, seg, nsegs, false, &mr); |
383 | if (IS_ERR(seg)) | 404 | if (IS_ERR(seg)) |
384 | return PTR_ERR(seg); | 405 | return PTR_ERR(seg); |
385 | rpcrdma_mr_push(mr, &req->rl_registered); | ||
386 | 406 | ||
387 | if (encode_read_segment(xdr, mr, pos) < 0) | 407 | if (encode_read_segment(xdr, mr, pos) < 0) |
388 | return -EMSGSIZE; | 408 | return -EMSGSIZE; |
@@ -440,10 +460,9 @@ rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, | |||
440 | 460 | ||
441 | nchunks = 0; | 461 | nchunks = 0; |
442 | do { | 462 | do { |
443 | seg = frwr_map(r_xprt, seg, nsegs, true, rqst->rq_xid, &mr); | 463 | seg = rpcrdma_mr_prepare(r_xprt, req, seg, nsegs, true, &mr); |
444 | if (IS_ERR(seg)) | 464 | if (IS_ERR(seg)) |
445 | return PTR_ERR(seg); | 465 | return PTR_ERR(seg); |
446 | rpcrdma_mr_push(mr, &req->rl_registered); | ||
447 | 466 | ||
448 | if (encode_rdma_segment(xdr, mr) < 0) | 467 | if (encode_rdma_segment(xdr, mr) < 0) |
449 | return -EMSGSIZE; | 468 | return -EMSGSIZE; |
@@ -501,10 +520,9 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, | |||
501 | 520 | ||
502 | nchunks = 0; | 521 | nchunks = 0; |
503 | do { | 522 | do { |
504 | seg = frwr_map(r_xprt, seg, nsegs, true, rqst->rq_xid, &mr); | 523 | seg = rpcrdma_mr_prepare(r_xprt, req, seg, nsegs, true, &mr); |
505 | if (IS_ERR(seg)) | 524 | if (IS_ERR(seg)) |
506 | return PTR_ERR(seg); | 525 | return PTR_ERR(seg); |
507 | rpcrdma_mr_push(mr, &req->rl_registered); | ||
508 | 526 | ||
509 | if (encode_rdma_segment(xdr, mr) < 0) | 527 | if (encode_rdma_segment(xdr, mr) < 0) |
510 | return -EMSGSIZE; | 528 | return -EMSGSIZE; |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 5e0b774ed522..c9fa0f27b10a 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -408,7 +408,7 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia) | |||
408 | struct rpcrdma_req *req; | 408 | struct rpcrdma_req *req; |
409 | struct rpcrdma_rep *rep; | 409 | struct rpcrdma_rep *rep; |
410 | 410 | ||
411 | cancel_delayed_work_sync(&buf->rb_refresh_worker); | 411 | cancel_work_sync(&buf->rb_refresh_worker); |
412 | 412 | ||
413 | /* This is similar to rpcrdma_ep_destroy, but: | 413 | /* This is similar to rpcrdma_ep_destroy, but: |
414 | * - Don't cancel the connect worker. | 414 | * - Don't cancel the connect worker. |
@@ -975,7 +975,7 @@ static void | |||
975 | rpcrdma_mr_refresh_worker(struct work_struct *work) | 975 | rpcrdma_mr_refresh_worker(struct work_struct *work) |
976 | { | 976 | { |
977 | struct rpcrdma_buffer *buf = container_of(work, struct rpcrdma_buffer, | 977 | struct rpcrdma_buffer *buf = container_of(work, struct rpcrdma_buffer, |
978 | rb_refresh_worker.work); | 978 | rb_refresh_worker); |
979 | struct rpcrdma_xprt *r_xprt = container_of(buf, struct rpcrdma_xprt, | 979 | struct rpcrdma_xprt *r_xprt = container_of(buf, struct rpcrdma_xprt, |
980 | rx_buf); | 980 | rx_buf); |
981 | 981 | ||
@@ -1086,8 +1086,7 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt) | |||
1086 | spin_lock_init(&buf->rb_lock); | 1086 | spin_lock_init(&buf->rb_lock); |
1087 | INIT_LIST_HEAD(&buf->rb_mrs); | 1087 | INIT_LIST_HEAD(&buf->rb_mrs); |
1088 | INIT_LIST_HEAD(&buf->rb_all_mrs); | 1088 | INIT_LIST_HEAD(&buf->rb_all_mrs); |
1089 | INIT_DELAYED_WORK(&buf->rb_refresh_worker, | 1089 | INIT_WORK(&buf->rb_refresh_worker, rpcrdma_mr_refresh_worker); |
1090 | rpcrdma_mr_refresh_worker); | ||
1091 | 1090 | ||
1092 | rpcrdma_mrs_create(r_xprt); | 1091 | rpcrdma_mrs_create(r_xprt); |
1093 | 1092 | ||
@@ -1177,7 +1176,7 @@ rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf) | |||
1177 | void | 1176 | void |
1178 | rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | 1177 | rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) |
1179 | { | 1178 | { |
1180 | cancel_delayed_work_sync(&buf->rb_refresh_worker); | 1179 | cancel_work_sync(&buf->rb_refresh_worker); |
1181 | 1180 | ||
1182 | rpcrdma_sendctxs_destroy(buf); | 1181 | rpcrdma_sendctxs_destroy(buf); |
1183 | 1182 | ||
@@ -1218,19 +1217,7 @@ rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt) | |||
1218 | spin_lock(&buf->rb_mrlock); | 1217 | spin_lock(&buf->rb_mrlock); |
1219 | mr = rpcrdma_mr_pop(&buf->rb_mrs); | 1218 | mr = rpcrdma_mr_pop(&buf->rb_mrs); |
1220 | spin_unlock(&buf->rb_mrlock); | 1219 | spin_unlock(&buf->rb_mrlock); |
1221 | if (!mr) | ||
1222 | goto out_nomrs; | ||
1223 | return mr; | 1220 | return mr; |
1224 | |||
1225 | out_nomrs: | ||
1226 | trace_xprtrdma_nomrs(r_xprt); | ||
1227 | if (r_xprt->rx_ep.rep_connected != -ENODEV) | ||
1228 | schedule_delayed_work(&buf->rb_refresh_worker, 0); | ||
1229 | |||
1230 | /* Allow the reply handler and refresh worker to run */ | ||
1231 | cond_resched(); | ||
1232 | |||
1233 | return NULL; | ||
1234 | } | 1221 | } |
1235 | 1222 | ||
1236 | /** | 1223 | /** |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 3e0839c2cda2..9573587ca602 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -379,7 +379,7 @@ struct rpcrdma_buffer { | |||
379 | u32 rb_bc_srv_max_requests; | 379 | u32 rb_bc_srv_max_requests; |
380 | u32 rb_bc_max_requests; | 380 | u32 rb_bc_max_requests; |
381 | 381 | ||
382 | struct delayed_work rb_refresh_worker; | 382 | struct work_struct rb_refresh_worker; |
383 | }; | 383 | }; |
384 | 384 | ||
385 | /* | 385 | /* |
@@ -548,7 +548,7 @@ size_t frwr_maxpages(struct rpcrdma_xprt *r_xprt); | |||
548 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, | 548 | struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt, |
549 | struct rpcrdma_mr_seg *seg, | 549 | struct rpcrdma_mr_seg *seg, |
550 | int nsegs, bool writing, __be32 xid, | 550 | int nsegs, bool writing, __be32 xid, |
551 | struct rpcrdma_mr **mr); | 551 | struct rpcrdma_mr *mr); |
552 | int frwr_send(struct rpcrdma_ia *ia, struct rpcrdma_req *req); | 552 | int frwr_send(struct rpcrdma_ia *ia, struct rpcrdma_req *req); |
553 | void frwr_reminv(struct rpcrdma_rep *rep, struct list_head *mrs); | 553 | void frwr_reminv(struct rpcrdma_rep *rep, struct list_head *mrs); |
554 | void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); | 554 | void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); |