Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: have svc_recv() check kthread_should_stop()

When using kthreads that call into svc_recv, we want to make sure that
they do not block there for a long time when we're trying to take down
the kthread.

This patch changes svc_recv() to check kthread_should_stop() at the same
places that it checks to see if it's signalled(). Also check just before
svc_recv() tries to schedule(). By making sure that we check it just
after setting the task state we can avoid having to use any locking or
signalling to ensure it doesn't block for a long time.

There's still a chance of a 500ms sleep if alloc_page() fails, but
that should be a rare occurrence and isn't a terribly long time in
the context of a kthread being taken down.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

authored by

Jeff Layton and committed by
J. Bruce Fields
7086721f 23d42ee2

+22 -2
+22 -2
net/sunrpc/svc_xprt.c
··· 18 18 #include <linux/skbuff.h> 19 19 #include <linux/file.h> 20 20 #include <linux/freezer.h> 21 + #include <linux/kthread.h> 21 22 #include <net/sock.h> 22 23 #include <net/checksum.h> 23 24 #include <net/ip.h> ··· 588 587 struct page *p = alloc_page(GFP_KERNEL); 589 588 if (!p) { 590 589 int j = msecs_to_jiffies(500); 590 + if (kthread_should_stop()) 591 + return -EINTR; 591 592 schedule_timeout_uninterruptible(j); 592 593 } 593 594 rqstp->rq_pages[i] = p; ··· 610 607 611 608 try_to_freeze(); 612 609 cond_resched(); 613 - if (signalled()) 610 + if (signalled() || kthread_should_stop()) 614 611 return -EINTR; 615 612 616 613 spin_lock_bh(&pool->sp_lock); ··· 629 626 * to bring down the daemons ... 630 627 */ 631 628 set_current_state(TASK_INTERRUPTIBLE); 629 + 630 + /* 631 + * checking kthread_should_stop() here allows us to avoid 632 + * locking and signalling when stopping kthreads that call 633 + * svc_recv. If the thread has already been woken up, then 634 + * we can exit here without sleeping. If not, then it 635 + * it'll be woken up quickly during the schedule_timeout 636 + */ 637 + if (kthread_should_stop()) { 638 + set_current_state(TASK_RUNNING); 639 + spin_unlock_bh(&pool->sp_lock); 640 + return -EINTR; 641 + } 642 + 632 643 add_wait_queue(&rqstp->rq_wait, &wait); 633 644 spin_unlock_bh(&pool->sp_lock); 634 645 ··· 658 641 svc_thread_dequeue(pool, rqstp); 659 642 spin_unlock_bh(&pool->sp_lock); 660 643 dprintk("svc: server %p, no data yet\n", rqstp); 661 - return signalled()? -EINTR : -EAGAIN; 644 + if (signalled() || kthread_should_stop()) 645 + return -EINTR; 646 + else 647 + return -EAGAIN; 662 648 } 663 649 } 664 650 spin_unlock_bh(&pool->sp_lock);