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

Configure Feed

Select the types of activity you want to include in your feed.

kthread: Fix task state in kthread worker if being frozen

When analyzing a kernel waring message, Peter pointed out that there is a race
condition when the kworker is being frozen and falls into try_to_freeze() with
TASK_INTERRUPTIBLE, which could trigger a might_sleep() warning in try_to_freeze().
Although the root cause is not related to freeze()[1], it is still worthy to fix
this issue ahead.

One possible race scenario:

CPU 0 CPU 1
----- -----

// kthread_worker_fn
set_current_state(TASK_INTERRUPTIBLE);
suspend_freeze_processes()
freeze_processes
static_branch_inc(&freezer_active);
freeze_kernel_threads
pm_nosig_freezing = true;
if (work) { //false
__set_current_state(TASK_RUNNING);

} else if (!freezing(current)) //false, been frozen

freezing():
if (static_branch_unlikely(&freezer_active))
if (pm_nosig_freezing)
return true;
schedule()
}

// state is still TASK_INTERRUPTIBLE
try_to_freeze()
might_sleep() <--- warning

Fix this by explicitly set the TASK_RUNNING before entering
try_to_freeze().

Fixes: b56c0d8937e6 ("kthread: implement kthread_worker")
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Suggested-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/lkml/Zs2ZoAcUsZMX2B%2FI@chenyu5-mobl2/ [1]

authored by

Chen Yu and committed by
Peter Zijlstra
6b9ccbc0 84d26528

+9 -1
+9 -1
kernel/kthread.c
··· 845 845 * event only cares about the address. 846 846 */ 847 847 trace_sched_kthread_work_execute_end(work, func); 848 - } else if (!freezing(current)) 848 + } else if (!freezing(current)) { 849 849 schedule(); 850 + } else { 851 + /* 852 + * Handle the case where the current remains 853 + * TASK_INTERRUPTIBLE. try_to_freeze() expects 854 + * the current to be TASK_RUNNING. 855 + */ 856 + __set_current_state(TASK_RUNNING); 857 + } 850 858 851 859 try_to_freeze(); 852 860 cond_resched();