summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMandeep Singh Baines <msb@chromium.org>2012-01-03 14:41:13 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-06 14:14:13 -0800
commitc61e023d2b6ca9d0aaf766659a81ad5d017e5b53 (patch)
tree959303b1093bdaa92f640a54e0692881aed9e370
parente343400d67fa390709d8147972eb4b700018811b (diff)
downloadlwn-c61e023d2b6ca9d0aaf766659a81ad5d017e5b53.tar.gz
lwn-c61e023d2b6ca9d0aaf766659a81ad5d017e5b53.zip
hung_task: fix false positive during vfork
commit f9fab10bbd768b0e5254e53a4a8477a94bfc4b96 upstream. vfork parent uninterruptibly and unkillably waits for its child to exec/exit. This wait is of unbounded length. Ignore such waits in the hung_task detector. Signed-off-by: Mandeep Singh Baines <msb@chromium.org> Reported-by: Sasha Levin <levinsasha928@gmail.com> LKML-Reference: <1325344394.28904.43.camel@lappy> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: John Kacur <jkacur@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--kernel/hung_task.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index ea640120ab86..e972276f12ff 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -74,11 +74,17 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
/*
* Ensure the task is not frozen.
- * Also, when a freshly created task is scheduled once, changes
- * its state to TASK_UNINTERRUPTIBLE without having ever been
- * switched out once, it musn't be checked.
+ * Also, skip vfork and any other user process that freezer should skip.
*/
- if (unlikely(t->flags & PF_FROZEN || !switch_count))
+ if (unlikely(t->flags & (PF_FROZEN | PF_FREEZER_SKIP)))
+ return;
+
+ /*
+ * When a freshly created task is scheduled once, changes its state to
+ * TASK_UNINTERRUPTIBLE without having ever been switched out once, it
+ * musn't be checked.
+ */
+ if (unlikely(!switch_count))
return;
if (switch_count != t->last_switch_count) {