diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-06-24 10:55:50 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2016-07-13 15:53:48 -0400 |
commit | ff3ac5c3dc2323ba54c3d9ef30ef4942a71b251d (patch) | |
tree | 5efd439be1327a0c48c9103336e113186d3051cd /net | |
parent | 4720b0703a0dfcd6da6a308ea71aaacc55beade7 (diff) |
SUNRPC: Add a server side per-connection limit
Allow the user to limit the number of requests serviced through a single
connection, to help prevent faster clients from starving slower clients.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index e7082a4aeb56..2adc8db6aaf5 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -21,6 +21,10 @@ | |||
21 | 21 | ||
22 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 22 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
23 | 23 | ||
24 | static unsigned int svc_rpc_per_connection_limit __read_mostly; | ||
25 | module_param(svc_rpc_per_connection_limit, uint, 0644); | ||
26 | |||
27 | |||
24 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); | 28 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); |
25 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 29 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
26 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 30 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
@@ -329,12 +333,41 @@ char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len) | |||
329 | } | 333 | } |
330 | EXPORT_SYMBOL_GPL(svc_print_addr); | 334 | EXPORT_SYMBOL_GPL(svc_print_addr); |
331 | 335 | ||
336 | static bool svc_xprt_slots_in_range(struct svc_xprt *xprt) | ||
337 | { | ||
338 | unsigned int limit = svc_rpc_per_connection_limit; | ||
339 | int nrqsts = atomic_read(&xprt->xpt_nr_rqsts); | ||
340 | |||
341 | return limit == 0 || (nrqsts >= 0 && nrqsts < limit); | ||
342 | } | ||
343 | |||
344 | static bool svc_xprt_reserve_slot(struct svc_rqst *rqstp, struct svc_xprt *xprt) | ||
345 | { | ||
346 | if (!test_bit(RQ_DATA, &rqstp->rq_flags)) { | ||
347 | if (!svc_xprt_slots_in_range(xprt)) | ||
348 | return false; | ||
349 | atomic_inc(&xprt->xpt_nr_rqsts); | ||
350 | set_bit(RQ_DATA, &rqstp->rq_flags); | ||
351 | } | ||
352 | return true; | ||
353 | } | ||
354 | |||
355 | static void svc_xprt_release_slot(struct svc_rqst *rqstp) | ||
356 | { | ||
357 | struct svc_xprt *xprt = rqstp->rq_xprt; | ||
358 | if (test_and_clear_bit(RQ_DATA, &rqstp->rq_flags)) { | ||
359 | atomic_dec(&xprt->xpt_nr_rqsts); | ||
360 | svc_xprt_enqueue(xprt); | ||
361 | } | ||
362 | } | ||
363 | |||
332 | static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) | 364 | static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) |
333 | { | 365 | { |
334 | if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) | 366 | if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) |
335 | return true; | 367 | return true; |
336 | if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) { | 368 | if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) { |
337 | if (xprt->xpt_ops->xpo_has_wspace(xprt)) | 369 | if (xprt->xpt_ops->xpo_has_wspace(xprt) && |
370 | svc_xprt_slots_in_range(xprt)) | ||
338 | return true; | 371 | return true; |
339 | trace_svc_xprt_no_write_space(xprt); | 372 | trace_svc_xprt_no_write_space(xprt); |
340 | return false; | 373 | return false; |
@@ -516,8 +549,8 @@ static void svc_xprt_release(struct svc_rqst *rqstp) | |||
516 | 549 | ||
517 | rqstp->rq_res.head[0].iov_len = 0; | 550 | rqstp->rq_res.head[0].iov_len = 0; |
518 | svc_reserve(rqstp, 0); | 551 | svc_reserve(rqstp, 0); |
552 | svc_xprt_release_slot(rqstp); | ||
519 | rqstp->rq_xprt = NULL; | 553 | rqstp->rq_xprt = NULL; |
520 | |||
521 | svc_xprt_put(xprt); | 554 | svc_xprt_put(xprt); |
522 | } | 555 | } |
523 | 556 | ||
@@ -785,7 +818,7 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
785 | svc_add_new_temp_xprt(serv, newxpt); | 818 | svc_add_new_temp_xprt(serv, newxpt); |
786 | else | 819 | else |
787 | module_put(xprt->xpt_class->xcl_owner); | 820 | module_put(xprt->xpt_class->xcl_owner); |
788 | } else { | 821 | } else if (svc_xprt_reserve_slot(rqstp, xprt)) { |
789 | /* XPT_DATA|XPT_DEFERRED case: */ | 822 | /* XPT_DATA|XPT_DEFERRED case: */ |
790 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 823 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
791 | rqstp, rqstp->rq_pool->sp_id, xprt, | 824 | rqstp, rqstp->rq_pool->sp_id, xprt, |