Skip to content

Commit 9d6b040

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Place registered MWs on a per-req list
Instead of placing registered MWs sparsely into the rl_segments array, place these MWs on a per-req list. ro_unmap_{sync,safe} can then simply pull those MWs off the list instead of walking through the array. This change significantly reduces the size of struct rpcrdma_req by removing nsegs and rl_mw from every array element. As an additional clean-up, chunk co-ordinates are returned in the "*mw" output argument so they are no longer needed in every array element. Signed-off-by: Chuck Lever <[email protected]> Tested-by: Steve Wise <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 2ffc871 commit 9d6b040

File tree

6 files changed

+94
-139
lines changed

6 files changed

+94
-139
lines changed

net/sunrpc/xprtrdma/fmr_ops.c

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ fmr_op_release_mr(struct rpcrdma_mw *r)
101101
LIST_HEAD(unmap_list);
102102
int rc;
103103

104+
/* Ensure MW is not on any rl_registered list */
105+
if (!list_empty(&r->mw_list))
106+
list_del(&r->mw_list);
107+
104108
kfree(r->fmr.fm_physaddrs);
105109
kfree(r->mw_sg);
106110

@@ -176,17 +180,13 @@ fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
176180
*/
177181
static int
178182
fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
179-
int nsegs, bool writing)
183+
int nsegs, bool writing, struct rpcrdma_mw **out)
180184
{
181185
struct rpcrdma_mr_seg *seg1 = seg;
182186
int len, pageoff, i, rc;
183187
struct rpcrdma_mw *mw;
184188
u64 *dma_pages;
185189

186-
mw = seg1->rl_mw;
187-
seg1->rl_mw = NULL;
188-
if (mw)
189-
rpcrdma_defer_mr_recovery(mw);
190190
mw = rpcrdma_get_mw(r_xprt);
191191
if (!mw)
192192
return -ENOBUFS;
@@ -230,11 +230,11 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
230230
if (rc)
231231
goto out_maperr;
232232

233-
seg1->rl_mw = mw;
234-
seg1->mr_rkey = mw->fmr.fm_mr->rkey;
235-
seg1->mr_base = dma_pages[0] + pageoff;
236-
seg1->mr_nsegs = mw->mw_nents;
237-
seg1->mr_len = len;
233+
mw->mw_handle = mw->fmr.fm_mr->rkey;
234+
mw->mw_length = len;
235+
mw->mw_offset = dma_pages[0] + pageoff;
236+
237+
*out = mw;
238238
return mw->mw_nents;
239239

240240
out_dmamap_err:
@@ -255,13 +255,13 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
255255
*
256256
* Sleeps until it is safe for the host CPU to access the
257257
* previously mapped memory regions.
258+
*
259+
* Caller ensures that req->rl_registered is not empty.
258260
*/
259261
static void
260262
fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
261263
{
262-
struct rpcrdma_mr_seg *seg;
263-
unsigned int i, nchunks;
264-
struct rpcrdma_mw *mw;
264+
struct rpcrdma_mw *mw, *tmp;
265265
LIST_HEAD(unmap_list);
266266
int rc;
267267

@@ -272,49 +272,31 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
272272
* ib_unmap_fmr() is slow, so use a single call instead
273273
* of one call per mapped FMR.
274274
*/
275-
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
276-
seg = &req->rl_segments[i];
277-
mw = seg->rl_mw;
278-
275+
list_for_each_entry(mw, &req->rl_registered, mw_list)
279276
list_add_tail(&mw->fmr.fm_mr->list, &unmap_list);
280-
281-
i += seg->mr_nsegs;
282-
}
283277
rc = ib_unmap_fmr(&unmap_list);
284278
if (rc)
285279
goto out_reset;
286280

287281
/* ORDER: Now DMA unmap all of the req's MRs, and return
288282
* them to the free MW list.
289283
*/
290-
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
291-
seg = &req->rl_segments[i];
292-
mw = seg->rl_mw;
293-
284+
list_for_each_entry_safe(mw, tmp, &req->rl_registered, mw_list) {
285+
list_del_init(&mw->mw_list);
294286
list_del_init(&mw->fmr.fm_mr->list);
295287
ib_dma_unmap_sg(r_xprt->rx_ia.ri_device,
296288
mw->mw_sg, mw->mw_nents, mw->mw_dir);
297289
rpcrdma_put_mw(r_xprt, mw);
298-
299-
i += seg->mr_nsegs;
300-
seg->mr_nsegs = 0;
301-
seg->rl_mw = NULL;
302290
}
303291

304-
req->rl_nchunks = 0;
305292
return;
306293

307294
out_reset:
308295
pr_err("rpcrdma: ib_unmap_fmr failed (%i)\n", rc);
309296

310-
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
311-
seg = &req->rl_segments[i];
312-
mw = seg->rl_mw;
313-
297+
list_for_each_entry_safe(mw, tmp, &req->rl_registered, mw_list) {
314298
list_del_init(&mw->fmr.fm_mr->list);
315299
fmr_op_recover_mr(mw);
316-
317-
i += seg->mr_nsegs;
318300
}
319301
}
320302

@@ -325,22 +307,17 @@ static void
325307
fmr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
326308
bool sync)
327309
{
328-
struct rpcrdma_mr_seg *seg;
329310
struct rpcrdma_mw *mw;
330-
unsigned int i;
331311

332-
for (i = 0; req->rl_nchunks; req->rl_nchunks--) {
333-
seg = &req->rl_segments[i];
334-
mw = seg->rl_mw;
312+
while (!list_empty(&req->rl_registered)) {
313+
mw = list_first_entry(&req->rl_registered,
314+
struct rpcrdma_mw, mw_list);
315+
list_del_init(&mw->mw_list);
335316

336317
if (sync)
337318
fmr_op_recover_mr(mw);
338319
else
339320
rpcrdma_defer_mr_recovery(mw);
340-
341-
i += seg->mr_nsegs;
342-
seg->mr_nsegs = 0;
343-
seg->rl_mw = NULL;
344321
}
345322
}
346323

net/sunrpc/xprtrdma/frwr_ops.c

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ frwr_op_release_mr(struct rpcrdma_mw *r)
128128
{
129129
int rc;
130130

131+
/* Ensure MW is not on any rl_registered list */
132+
if (!list_empty(&r->mw_list))
133+
list_del(&r->mw_list);
134+
131135
rc = ib_dereg_mr(r->frmr.fr_mr);
132136
if (rc)
133137
pr_err("rpcrdma: final ib_dereg_mr for %p returned %i\n",
@@ -333,10 +337,9 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
333337
*/
334338
static int
335339
frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
336-
int nsegs, bool writing)
340+
int nsegs, bool writing, struct rpcrdma_mw **out)
337341
{
338342
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
339-
struct rpcrdma_mr_seg *seg1 = seg;
340343
struct rpcrdma_mw *mw;
341344
struct rpcrdma_frmr *frmr;
342345
struct ib_mr *mr;
@@ -345,8 +348,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
345348
int rc, i, n, dma_nents;
346349
u8 key;
347350

348-
mw = seg1->rl_mw;
349-
seg1->rl_mw = NULL;
351+
mw = NULL;
350352
do {
351353
if (mw)
352354
rpcrdma_defer_mr_recovery(mw);
@@ -416,12 +418,11 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
416418
if (rc)
417419
goto out_senderr;
418420

419-
seg1->rl_mw = mw;
420-
seg1->mr_rkey = mr->rkey;
421-
seg1->mr_base = mr->iova;
422-
seg1->mr_nsegs = mw->mw_nents;
423-
seg1->mr_len = mr->length;
421+
mw->mw_handle = mr->rkey;
422+
mw->mw_length = mr->length;
423+
mw->mw_offset = mr->iova;
424424

425+
*out = mw;
425426
return mw->mw_nents;
426427

427428
out_dmamap_err:
@@ -443,9 +444,8 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
443444
}
444445

445446
static struct ib_send_wr *
446-
__frwr_prepare_linv_wr(struct rpcrdma_mr_seg *seg)
447+
__frwr_prepare_linv_wr(struct rpcrdma_mw *mw)
447448
{
448-
struct rpcrdma_mw *mw = seg->rl_mw;
449449
struct rpcrdma_frmr *f = &mw->frmr;
450450
struct ib_send_wr *invalidate_wr;
451451

@@ -465,16 +465,16 @@ __frwr_prepare_linv_wr(struct rpcrdma_mr_seg *seg)
465465
*
466466
* Sleeps until it is safe for the host CPU to access the
467467
* previously mapped memory regions.
468+
*
469+
* Caller ensures that req->rl_registered is not empty.
468470
*/
469471
static void
470472
frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
471473
{
472474
struct ib_send_wr *invalidate_wrs, *pos, *prev, *bad_wr;
473475
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
474-
struct rpcrdma_mr_seg *seg;
475-
unsigned int i, nchunks;
476+
struct rpcrdma_mw *mw, *tmp;
476477
struct rpcrdma_frmr *f;
477-
struct rpcrdma_mw *mw;
478478
int rc;
479479

480480
dprintk("RPC: %s: req %p\n", __func__, req);
@@ -484,22 +484,18 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
484484
* Chain the LOCAL_INV Work Requests and post them with
485485
* a single ib_post_send() call.
486486
*/
487+
f = NULL;
487488
invalidate_wrs = pos = prev = NULL;
488-
seg = NULL;
489-
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
490-
seg = &req->rl_segments[i];
491-
492-
pos = __frwr_prepare_linv_wr(seg);
489+
list_for_each_entry(mw, &req->rl_registered, mw_list) {
490+
pos = __frwr_prepare_linv_wr(mw);
493491

494492
if (!invalidate_wrs)
495493
invalidate_wrs = pos;
496494
else
497495
prev->next = pos;
498496
prev = pos;
499-
500-
i += seg->mr_nsegs;
497+
f = &mw->frmr;
501498
}
502-
f = &seg->rl_mw->frmr;
503499

504500
/* Strong send queue ordering guarantees that when the
505501
* last WR in the chain completes, all WRs in the chain
@@ -524,20 +520,12 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
524520
* them to the free MW list.
525521
*/
526522
unmap:
527-
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
528-
seg = &req->rl_segments[i];
529-
mw = seg->rl_mw;
530-
seg->rl_mw = NULL;
531-
523+
list_for_each_entry_safe(mw, tmp, &req->rl_registered, mw_list) {
524+
list_del_init(&mw->mw_list);
532525
ib_dma_unmap_sg(ia->ri_device,
533526
mw->mw_sg, mw->mw_nents, mw->mw_dir);
534527
rpcrdma_put_mw(r_xprt, mw);
535-
536-
i += seg->mr_nsegs;
537-
seg->mr_nsegs = 0;
538528
}
539-
540-
req->rl_nchunks = 0;
541529
return;
542530

543531
reset_mrs:
@@ -547,17 +535,12 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
547535
/* Find and reset the MRs in the LOCAL_INV WRs that did not
548536
* get posted. This is synchronous, and slow.
549537
*/
550-
for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
551-
seg = &req->rl_segments[i];
552-
mw = seg->rl_mw;
538+
list_for_each_entry(mw, &req->rl_registered, mw_list) {
553539
f = &mw->frmr;
554-
555540
if (mw->frmr.fr_mr->rkey == bad_wr->ex.invalidate_rkey) {
556541
__frwr_reset_mr(ia, mw);
557542
bad_wr = bad_wr->next;
558543
}
559-
560-
i += seg->mr_nsegs;
561544
}
562545
goto unmap;
563546
}
@@ -569,22 +552,17 @@ static void
569552
frwr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
570553
bool sync)
571554
{
572-
struct rpcrdma_mr_seg *seg;
573555
struct rpcrdma_mw *mw;
574-
unsigned int i;
575556

576-
for (i = 0; req->rl_nchunks; req->rl_nchunks--) {
577-
seg = &req->rl_segments[i];
578-
mw = seg->rl_mw;
557+
while (!list_empty(&req->rl_registered)) {
558+
mw = list_first_entry(&req->rl_registered,
559+
struct rpcrdma_mw, mw_list);
560+
list_del_init(&mw->mw_list);
579561

580562
if (sync)
581563
frwr_op_recover_mr(mw);
582564
else
583565
rpcrdma_defer_mr_recovery(mw);
584-
585-
i += seg->mr_nsegs;
586-
seg->mr_nsegs = 0;
587-
seg->rl_mw = NULL;
588566
}
589567
}
590568

0 commit comments

Comments
 (0)