diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index e588df5d6b34..0551b6b6cf8c 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 15 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
16 | 16 | ||
17 | #define SVC_MAX_WAKING 5 | ||
18 | |||
17 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); | 19 | static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); |
18 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 20 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
19 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 21 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
@@ -298,6 +300,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
298 | struct svc_pool *pool; | 300 | struct svc_pool *pool; |
299 | struct svc_rqst *rqstp; | 301 | struct svc_rqst *rqstp; |
300 | int cpu; | 302 | int cpu; |
303 | int thread_avail; | ||
301 | 304 | ||
302 | if (!(xprt->xpt_flags & | 305 | if (!(xprt->xpt_flags & |
303 | ((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED)))) | 306 | ((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED)))) |
@@ -309,12 +312,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
309 | 312 | ||
310 | spin_lock_bh(&pool->sp_lock); | 313 | spin_lock_bh(&pool->sp_lock); |
311 | 314 | ||
312 | if (!list_empty(&pool->sp_threads) && | ||
313 | !list_empty(&pool->sp_sockets)) | ||
314 | printk(KERN_ERR | ||
315 | "svc_xprt_enqueue: " | ||
316 | "threads and transports both waiting??\n"); | ||
317 | |||
318 | if (test_bit(XPT_DEAD, &xprt->xpt_flags)) { | 315 | if (test_bit(XPT_DEAD, &xprt->xpt_flags)) { |
319 | /* Don't enqueue dead transports */ | 316 | /* Don't enqueue dead transports */ |
320 | dprintk("svc: transport %p is dead, not enqueued\n", xprt); | 317 | dprintk("svc: transport %p is dead, not enqueued\n", xprt); |
@@ -353,7 +350,14 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
353 | } | 350 | } |
354 | 351 | ||
355 | process: | 352 | process: |
356 | if (!list_empty(&pool->sp_threads)) { | 353 | /* Work out whether threads are available */ |
354 | thread_avail = !list_empty(&pool->sp_threads); /* threads are asleep */ | ||
355 | if (pool->sp_nwaking >= SVC_MAX_WAKING) { | ||
356 | /* too many threads are runnable and trying to wake up */ | ||
357 | thread_avail = 0; | ||
358 | } | ||
359 | |||
360 | if (thread_avail) { | ||
357 | rqstp = list_entry(pool->sp_threads.next, | 361 | rqstp = list_entry(pool->sp_threads.next, |
358 | struct svc_rqst, | 362 | struct svc_rqst, |
359 | rq_list); | 363 | rq_list); |
@@ -368,6 +372,8 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
368 | svc_xprt_get(xprt); | 372 | svc_xprt_get(xprt); |
369 | rqstp->rq_reserved = serv->sv_max_mesg; | 373 | rqstp->rq_reserved = serv->sv_max_mesg; |
370 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | 374 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); |
375 | rqstp->rq_waking = 1; | ||
376 | pool->sp_nwaking++; | ||
371 | BUG_ON(xprt->xpt_pool != pool); | 377 | BUG_ON(xprt->xpt_pool != pool); |
372 | wake_up(&rqstp->rq_wait); | 378 | wake_up(&rqstp->rq_wait); |
373 | } else { | 379 | } else { |
@@ -633,6 +639,11 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
633 | return -EINTR; | 639 | return -EINTR; |
634 | 640 | ||
635 | spin_lock_bh(&pool->sp_lock); | 641 | spin_lock_bh(&pool->sp_lock); |
642 | if (rqstp->rq_waking) { | ||
643 | rqstp->rq_waking = 0; | ||
644 | pool->sp_nwaking--; | ||
645 | BUG_ON(pool->sp_nwaking < 0); | ||
646 | } | ||
636 | xprt = svc_xprt_dequeue(pool); | 647 | xprt = svc_xprt_dequeue(pool); |
637 | if (xprt) { | 648 | if (xprt) { |
638 | rqstp->rq_xprt = xprt; | 649 | rqstp->rq_xprt = xprt; |