diff options
author | Miroslav Benes <mbenes@suse.cz> | 2016-11-23 11:16:50 +0100 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2016-11-24 15:52:47 +0100 |
commit | 240cb3f4fd53bef71809a2d71e15617147196091 (patch) | |
tree | 11056e2cde1c3dfa9f18319b4c5fc33d9a80f0e6 | |
parent | a5b64df4284636abc5f4964df4601336ffcc9cc9 (diff) | |
download | kgraft-4.4.tar.gz |
kgr: ignore zombie tasks during the patchingkgraft-4.4
There is no special treatment of zombie tasks in kGraft. This means that
they can block the patching process almost infinitely if their
TIF_KGR_IN_PROGRESS flag is set, because they cannot run anymore and
cannot clear the flag.
Simple reproducer:
# echo 'main() { if(fork()) sleep(300); }' > zombie.c
# gcc -o zombie zombie.c
# ./zombie &
# ps xa | fgrep Z
# zypper in -t pattern lp_sles
... installation running
# kgr status
in_progress
# kgr -vv blocking
2705 [zombie]
[<ffffffff8105b877>] do_exit+0x6f7/0xa80
[<ffffffff8105bc79>] do_group_exit+0x39/0xa0
[<ffffffff8105bcf0>] __wake_up_parent+0x0/0x30
[<ffffffff8152dd09>] system_call_fastpath+0x16/0x1b
[<00007fd128f9c4f9>] 0x7fd128f9c4f9
[<ffffffffffffffff>] 0xffffffffffffffff
Let's ignore the zombie tasks in kgr_still_patching() check. Such task
is in TASK_DEAD state. We also need to be sure that the task is not
running anymore. Otherwise there would be unpleasant race conditions. So
also check task's ->on_cpu. It is set to 0 by the next task in
finish_lock_switch().
Signed-off-by: Miroslav Benes <mbenes@suse.cz>
Acked-by: Jiri Kosina <jkosina@suse.cz>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-rw-r--r-- | kernel/kgraft.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/kernel/kgraft.c b/kernel/kgraft.c index 39fa267057174a..395b2c7bd64bb1 100644 --- a/kernel/kgraft.c +++ b/kernel/kgraft.c @@ -152,7 +152,13 @@ static bool kgr_still_patching(void) read_lock(&tasklist_lock); for_each_process_thread(p, t) { - if (klp_kgraft_task_in_progress(t)) { + /* + * Ignore zombie tasks, that is task with ->state == TASK_DEAD. + * We also need to check their ->on_cpu to be sure that they are + * not running any code and they are really almost dead. + */ + if (klp_kgraft_task_in_progress(t) && (t->state != TASK_DEAD || + t->on_cpu != 0)) { failed = true; goto unlock; } |