aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-06-24 10:55:50 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-07-13 15:53:48 -0400
commitff3ac5c3dc2323ba54c3d9ef30ef4942a71b251d (patch)
tree5efd439be1327a0c48c9103336e113186d3051cd /net
parent4720b0703a0dfcd6da6a308ea71aaacc55beade7 (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.c39
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
24static unsigned int svc_rpc_per_connection_limit __read_mostly;
25module_param(svc_rpc_per_connection_limit, uint, 0644);
26
27
24static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); 28static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
25static int svc_deferred_recv(struct svc_rqst *rqstp); 29static int svc_deferred_recv(struct svc_rqst *rqstp);
26static struct cache_deferred_req *svc_defer(struct cache_req *req); 30static 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}
330EXPORT_SYMBOL_GPL(svc_print_addr); 334EXPORT_SYMBOL_GPL(svc_print_addr);
331 335
336static 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
344static 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
355static 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
332static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) 364static 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,