Skip to content

Commit 9d2da4f

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Manage MRs in context of a single connection
MRs are now allocated on demand so we can safely throw them away on disconnect. This way an idle transport can disconnect and it won't pin hardware MR resources. Two additional changes: - Now that all MRs are destroyed on disconnect, there's no need to check during header marshaling if a req has MRs to recycle. Each req is sent only once per connection, and now rl_registered is guaranteed to be empty when rpcrdma_marshal_req is invoked. - Because MRs are now destroyed in a WQ_MEM_RECLAIM context, they also must be allocated in a WQ_MEM_RECLAIM context. This reduces the likelihood that device driver memory allocation will trigger memory reclaim during NFS writeback. Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent c370078 commit 9d2da4f

File tree

4 files changed

+40
-57
lines changed

4 files changed

+40
-57
lines changed

net/sunrpc/xprtrdma/frwr_ops.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
* connect worker from running concurrently.
3737
*
3838
* When the underlying transport disconnects, MRs that are in flight
39-
* are flushed and are likely unusable. Thus all flushed MRs are
40-
* destroyed. New MRs are created on demand.
39+
* are flushed and are likely unusable. Thus all MRs are destroyed.
40+
* New MRs are created on demand.
4141
*/
4242

4343
#include <linux/sunrpc/rpc_rdma.h>
@@ -119,20 +119,6 @@ frwr_mr_recycle_worker(struct work_struct *work)
119119
frwr_mr_recycle(mr->mr_xprt, mr);
120120
}
121121

122-
/* frwr_recycle - Discard MRs
123-
* @req: request to reset
124-
*
125-
* Used after a reconnect. These MRs could be in flight, we can't
126-
* tell. Safe thing to do is release them.
127-
*/
128-
void frwr_recycle(struct rpcrdma_req *req)
129-
{
130-
struct rpcrdma_mr *mr;
131-
132-
while ((mr = rpcrdma_mr_pop(&req->rl_registered)))
133-
frwr_mr_recycle(mr->mr_xprt, mr);
134-
}
135-
136122
/* frwr_reset - Place MRs back on the free list
137123
* @req: request to reset
138124
*
@@ -166,9 +152,6 @@ int frwr_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mr *mr)
166152
struct ib_mr *frmr;
167153
int rc;
168154

169-
/* NB: ib_alloc_mr and device drivers typically allocate
170-
* memory with GFP_KERNEL.
171-
*/
172155
frmr = ib_alloc_mr(ia->ri_pd, ia->ri_mrtype, depth);
173156
if (IS_ERR(frmr))
174157
goto out_mr_err;
@@ -440,9 +423,6 @@ int frwr_send(struct rpcrdma_ia *ia, struct rpcrdma_req *req)
440423
post_wr = &frwr->fr_regwr.wr;
441424
}
442425

443-
/* If ib_post_send fails, the next ->send_request for
444-
* @req will queue these MRs for recovery.
445-
*/
446426
return ib_post_send(ia->ri_id->qp, post_wr, NULL);
447427
}
448428

net/sunrpc/xprtrdma/rpc_rdma.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,7 @@ static struct rpcrdma_mr_seg *rpcrdma_mr_prepare(struct rpcrdma_xprt *r_xprt,
363363
out_getmr_err:
364364
trace_xprtrdma_nomrs(req);
365365
xprt_wait_for_buffer_space(&r_xprt->rx_xprt);
366-
if (r_xprt->rx_ep.rep_connected != -ENODEV)
367-
schedule_work(&r_xprt->rx_buf.rb_refresh_worker);
366+
rpcrdma_mrs_refresh(r_xprt);
368367
return ERR_PTR(-EAGAIN);
369368
}
370369

@@ -863,12 +862,6 @@ rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst)
863862
rtype = rpcrdma_areadch;
864863
}
865864

866-
/* If this is a retransmit, discard previously registered
867-
* chunks. Very likely the connection has been replaced,
868-
* so these registrations are invalid and unusable.
869-
*/
870-
frwr_recycle(req);
871-
872865
/* This implementation supports the following combinations
873866
* of chunk lists in one RPC-over-RDMA Call message:
874867
*

net/sunrpc/xprtrdma/verbs.c

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc);
7878
static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt);
7979
static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf);
8080
static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
81-
static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);
81+
static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt);
8282
static struct rpcrdma_regbuf *
8383
rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction,
8484
gfp_t flags);
@@ -407,8 +407,6 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
407407
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
408408
struct rpcrdma_req *req;
409409

410-
cancel_work_sync(&buf->rb_refresh_worker);
411-
412410
/* This is similar to rpcrdma_ep_destroy, but:
413411
* - Don't cancel the connect worker.
414412
* - Don't call rpcrdma_ep_disconnect, which waits
@@ -435,7 +433,7 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
435433
rpcrdma_regbuf_dma_unmap(req->rl_sendbuf);
436434
rpcrdma_regbuf_dma_unmap(req->rl_recvbuf);
437435
}
438-
rpcrdma_mrs_destroy(buf);
436+
rpcrdma_mrs_destroy(r_xprt);
439437
ib_dealloc_pd(ia->ri_pd);
440438
ia->ri_pd = NULL;
441439

@@ -628,8 +626,6 @@ static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
628626
pr_err("rpcrdma: rdma_create_qp returned %d\n", err);
629627
goto out3;
630628
}
631-
632-
rpcrdma_mrs_create(r_xprt);
633629
return 0;
634630

635631
out3:
@@ -703,7 +699,6 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
703699
memcpy(&qp_init_attr, &ep->rep_attr, sizeof(qp_init_attr));
704700
switch (ep->rep_connected) {
705701
case 0:
706-
dprintk("RPC: %s: connecting...\n", __func__);
707702
rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &qp_init_attr);
708703
if (rc) {
709704
rc = -ENETUNREACH;
@@ -741,7 +736,7 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
741736
goto out;
742737
}
743738

744-
dprintk("RPC: %s: connected\n", __func__);
739+
rpcrdma_mrs_create(r_xprt);
745740

746741
out:
747742
if (rc)
@@ -756,11 +751,8 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
756751
* @ep: endpoint to disconnect
757752
* @ia: associated interface adapter
758753
*
759-
* This is separate from destroy to facilitate the ability
760-
* to reconnect without recreating the endpoint.
761-
*
762-
* This call is not reentrant, and must not be made in parallel
763-
* on the same endpoint.
754+
* Caller serializes. Either the transport send lock is held,
755+
* or we're being called to destroy the transport.
764756
*/
765757
void
766758
rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
@@ -780,6 +772,7 @@ rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
780772

781773
rpcrdma_xprt_drain(r_xprt);
782774
rpcrdma_reqs_reset(r_xprt);
775+
rpcrdma_mrs_destroy(r_xprt);
783776
}
784777

785778
/* Fixed-size circular FIFO queue. This implementation is wait-free and
@@ -986,6 +979,28 @@ rpcrdma_mr_refresh_worker(struct work_struct *work)
986979
xprt_write_space(&r_xprt->rx_xprt);
987980
}
988981

982+
/**
983+
* rpcrdma_mrs_refresh - Wake the MR refresh worker
984+
* @r_xprt: controlling transport instance
985+
*
986+
*/
987+
void rpcrdma_mrs_refresh(struct rpcrdma_xprt *r_xprt)
988+
{
989+
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
990+
struct rpcrdma_ep *ep = &r_xprt->rx_ep;
991+
992+
/* If there is no underlying device, it's no use to
993+
* wake the refresh worker.
994+
*/
995+
if (ep->rep_connected != -ENODEV) {
996+
/* The work is scheduled on a WQ_MEM_RECLAIM
997+
* workqueue in order to prevent MR allocation
998+
* from recursing into NFS during direct reclaim.
999+
*/
1000+
queue_work(xprtiod_workqueue, &buf->rb_refresh_worker);
1001+
}
1002+
}
1003+
9891004
/**
9901005
* rpcrdma_req_create - Allocate an rpcrdma_req object
9911006
* @r_xprt: controlling r_xprt
@@ -1145,8 +1160,6 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
11451160
INIT_LIST_HEAD(&buf->rb_all_mrs);
11461161
INIT_WORK(&buf->rb_refresh_worker, rpcrdma_mr_refresh_worker);
11471162

1148-
rpcrdma_mrs_create(r_xprt);
1149-
11501163
INIT_LIST_HEAD(&buf->rb_send_bufs);
11511164
INIT_LIST_HEAD(&buf->rb_allreqs);
11521165

@@ -1177,8 +1190,8 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
11771190
* rpcrdma_req_destroy - Destroy an rpcrdma_req object
11781191
* @req: unused object to be destroyed
11791192
*
1180-
* This function assumes that the caller prevents concurrent device
1181-
* unload and transport tear-down.
1193+
* Relies on caller holding the transport send lock to protect
1194+
* removing req->rl_all from buf->rb_all_reqs safely.
11821195
*/
11831196
void rpcrdma_req_destroy(struct rpcrdma_req *req)
11841197
{
@@ -1204,17 +1217,18 @@ void rpcrdma_req_destroy(struct rpcrdma_req *req)
12041217

12051218
/**
12061219
* rpcrdma_mrs_destroy - Release all of a transport's MRs
1207-
* @buf: controlling buffer instance
1220+
* @r_xprt: controlling transport instance
12081221
*
12091222
* Relies on caller holding the transport send lock to protect
12101223
* removing mr->mr_list from req->rl_free_mrs safely.
12111224
*/
1212-
static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
1225+
static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt)
12131226
{
1214-
struct rpcrdma_xprt *r_xprt = container_of(buf, struct rpcrdma_xprt,
1215-
rx_buf);
1227+
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
12161228
struct rpcrdma_mr *mr;
12171229

1230+
cancel_work_sync(&buf->rb_refresh_worker);
1231+
12181232
spin_lock(&buf->rb_lock);
12191233
while ((mr = list_first_entry_or_null(&buf->rb_all_mrs,
12201234
struct rpcrdma_mr,
@@ -1224,10 +1238,10 @@ static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
12241238
spin_unlock(&buf->rb_lock);
12251239

12261240
frwr_release_mr(mr);
1241+
12271242
spin_lock(&buf->rb_lock);
12281243
}
12291244
spin_unlock(&buf->rb_lock);
1230-
r_xprt->rx_stats.mrs_allocated = 0;
12311245
}
12321246

12331247
/**
@@ -1241,8 +1255,6 @@ static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
12411255
void
12421256
rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
12431257
{
1244-
cancel_work_sync(&buf->rb_refresh_worker);
1245-
12461258
rpcrdma_sendctxs_destroy(buf);
12471259
rpcrdma_reps_destroy(buf);
12481260

@@ -1254,8 +1266,6 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
12541266
list_del(&req->rl_list);
12551267
rpcrdma_req_destroy(req);
12561268
}
1257-
1258-
rpcrdma_mrs_destroy(buf);
12591269
}
12601270

12611271
/**

net/sunrpc/xprtrdma/xprt_rdma.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_xprt *r_xprt);
488488

489489
struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt);
490490
void rpcrdma_mr_put(struct rpcrdma_mr *mr);
491+
void rpcrdma_mrs_refresh(struct rpcrdma_xprt *r_xprt);
491492

492493
static inline void
493494
rpcrdma_mr_recycle(struct rpcrdma_mr *mr)
@@ -543,7 +544,6 @@ rpcrdma_data_dir(bool writing)
543544
/* Memory registration calls xprtrdma/frwr_ops.c
544545
*/
545546
bool frwr_is_supported(struct ib_device *device);
546-
void frwr_recycle(struct rpcrdma_req *req);
547547
void frwr_reset(struct rpcrdma_req *req);
548548
int frwr_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep);
549549
int frwr_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mr *mr);

0 commit comments

Comments
 (0)