From: Jeff Layton Date: Tue, 12 Feb 2008 16:47:24 +0000 (-0500) Subject: SUNRPC: allow svc_recv to break out of 500ms sleep when alloc_page fails X-Git-Tag: v2.6.26-rc1~1083^2~35 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b54fe61ffd5bfa4e50d371a2415225aa0cbb38e;p=linux-2.6 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 Signed-off-by: J. Bruce Fields --- diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 2e5d43c391..d8e8d79a84 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) while (rqstp->rq_pages[i] == NULL) { struct page *p = alloc_page(GFP_KERNEL); if (!p) { - int j = msecs_to_jiffies(500); - if (kthread_should_stop()) + set_current_state(TASK_INTERRUPTIBLE); + if (signalled() || kthread_should_stop()) { + set_current_state(TASK_RUNNING); return -EINTR; - schedule_timeout_uninterruptible(j); + } + schedule_timeout(msecs_to_jiffies(500)); } rqstp->rq_pages[i] = p; }