aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-02-12 11:47:24 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-04-23 16:13:38 -0400
commit7b54fe61ffd5bfa4e50d371a2415225aa0cbb38e (patch)
tree6da4eb10c73ca75ff7cc94c11cfb11cd102447c4
parent6aaa67b5f3b9fe24f0c76d0415cc72e5a1137bea (diff)
SUNRPC: allow svc_recv to break out of 500ms sleep when alloc_page fails
svc_recv() calls alloc_page(), and if it fails it does a 500ms uninterruptible sleep and then reattempts. There doesn't seem to be any real reason for this to be uninterruptible, so change it to an interruptible sleep. Also check for kthread_stop() and signalled() after setting the task state to avoid races that might lead to sleeping after kthread_stop() wakes up the task. I've done some very basic smoke testing with this, but obviously it's hard to test the actual changes since this all depends on an alloc_page() call failing. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--net/sunrpc/svc_xprt.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 2e5d43c39142..d8e8d79a8451 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -587,10 +587,12 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
587 while (rqstp->rq_pages[i] == NULL) { 587 while (rqstp->rq_pages[i] == NULL) {
588 struct page *p = alloc_page(GFP_KERNEL); 588 struct page *p = alloc_page(GFP_KERNEL);
589 if (!p) { 589 if (!p) {
590 int j = msecs_to_jiffies(500); 590 set_current_state(TASK_INTERRUPTIBLE);
591 if (kthread_should_stop()) 591 if (signalled() || kthread_should_stop()) {
592 set_current_state(TASK_RUNNING);
592 return -EINTR; 593 return -EINTR;
593 schedule_timeout_uninterruptible(j); 594 }
595 schedule_timeout(msecs_to_jiffies(500));
594 } 596 }
595 rqstp->rq_pages[i] = p; 597 rqstp->rq_pages[i] = p;
596 } 598 }