[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <f4c4f465-72b9-4682-99e6-c249ecab8572@huaweicloud.com>
Date: Fri, 4 Jul 2025 11:02:52 +0800
From: Chen Ridong <chenridong@...weicloud.com>
To: Michal Koutný <mkoutny@...e.com>
Cc: peterz@...radead.org, rafael@...nel.org, pavel@...nel.org,
timvp@...gle.com, tj@...nel.org, linux-pm@...r.kernel.org,
linux-kernel@...r.kernel.org, lujialin4@...wei.com, chenridong@...wei.com
Subject: Re: [PATCH next] sched,freezer: prevent tasks from escaping being
frozen
On 2025/7/4 1:01, Michal Koutný wrote:
> Hello Ridong.
>
> On Thu, Jul 03, 2025 at 01:34:27PM +0000, Chen Ridong <chenridong@...weicloud.com> wrote:
>> 2. The cgroup freezer state changes to FROZEN (Can be triggered by reading
>> freezer.state).
> /o\
>
>> 3. freezing() is called and returns false.
>
> I can see how this can happen because freezer_lock != freezer_mutex.
>
>> As a result, the task may escape being frozen when it should be.
>>
>> To fix this, move the setting of the FROZEN flag to occur just before
>> schedule(). This ensures the flag is only set when we're certain the
>> task must be switched out.
>
> Is it sufficient? (If the task is spuriously woken up, the next
> iteration in that refrigerator loop would be subject to same race, no?)
>
> Thanks,
> Michal
Hi, Michal:
Regarding your question: Did you mean that the task was frozen, received
another signal to wake up, but should have remained frozen instead of
entering the running state?
For this scenario, the solution I've found is that the task can only
break out of the frozen state when its cgroup is thawed. The code
modification would look like the following, and we'll need to add the
cgroup_thawed(p) function:
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -71,19 +71,20 @@ bool __refrigerator(bool check_kthr_stop)
for (;;) {
bool freeze;
- raw_spin_lock_irq(¤t->pi_lock);
- WRITE_ONCE(current->__state, TASK_FROZEN);
- /* unstale saved_state so that __thaw_task() will wake
us up */
- current->saved_state = TASK_RUNNING;
- raw_spin_unlock_irq(¤t->pi_lock);
-
spin_lock_irq(&freezer_lock);
- freeze = freezing(current) && !(check_kthr_stop &&
kthread_should_stop());
+ freeze = (freezing(current) && !cgroup_thawed(current))
+ && !(check_kthr_stop && kthread_should_stop());
spin_unlock_irq(&freezer_lock);
if (!freeze)
break;
+ raw_spin_lock_irq(¤t->pi_lock);
+ WRITE_ONCE(current->__state, TASK_FROZEN);
+ /* unstale saved_state so that __thaw_task() will wake
us up */
+ current->saved_state = TASK_RUNNING;
+ raw_spin_unlock_irq(¤t->pi_lock);
+
I'd welcome any suggestions for better solutions to this problem.
Best regards,
Ridong
Powered by blists - more mailing lists