[Devel] [PATCH RHEL10 COMMIT] cgroup-v2/freezer: avoid sleeping allocations under RCU in freeze-timeout warning

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 15 17:18:24 MSK 2026


The commit is pushed to "branch-rh10-6.12.0-211.16.1.12.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-211.16.1.el10
------>
commit 59dac0d1c38ebfb91fcb2472deed5ddca6dac841
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
Date:   Thu Jun 4 00:03:34 2026 +0200

    cgroup-v2/freezer: avoid sleeping allocations under RCU in freeze-timeout warning
    
    warn_freeze_timeout() holds guard(rcu)() for its whole body (required by
    css_for_each_descendant_post()) and, inside that, both
    warn_freeze_timeout_task() and the "no unfreezable process" tail do
    kmalloc(PATH_MAX / stack-trace buffer, GFP_KERNEL). GFP_KERNEL may sleep,
    which is illegal inside an RCU read-side critical section ("sleeping
    function called from invalid context", caught by
    CONFIG_DEBUG_ATOMIC_SLEEP). The path is reachable from
    cgroup.events show -> check_freeze_timeout() -> warn_freeze_timeout() when
    a freeze exceeds sysctl_freeze_timeout and passes the ratelimit.
    
    The non-allocating work here (cgroup_path(), stack_trace_save_tsk()) is
    atomic-safe; only the allocations sleep. Use GFP_ATOMIC for the three
    buffers - this is a rare, ratelimited diagnostic path with small (<=PATH_MAX)
    allocations, so the stricter allocation context is acceptable.
    
    Fixes: e4bcc416ab19 ("cgroup-v2/freezer: Print information about unfreezable process")
    https://virtuozzo.atlassian.net/browse/VSTOR-132310
    Feature: cgroup/freeze: enhance logging
    Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 kernel/cgroup/cgroup.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 347b3761c37b..78a02ea49e8c 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -4129,7 +4129,13 @@ void warn_freeze_timeout_task(struct cgroup *cgrp, int timeout,
 	unsigned long nr_entries, i;
 	pid_t tgid;
 
-	buf = kmalloc(PATH_MAX, GFP_KERNEL);
+	/*
+	 * Called from warn_freeze_timeout() under rcu_read_lock() (the
+	 * css_for_each_descendant_post() iteration), so allocations here must
+	 * not sleep.  This is a rare, ratelimited diagnostic path with small
+	 * buffers, so GFP_ATOMIC is fine.
+	 */
+	buf = kmalloc(PATH_MAX, GFP_ATOMIC);
 	if (!buf)
 		return;
 
@@ -4142,7 +4148,7 @@ void warn_freeze_timeout_task(struct cgroup *cgrp, int timeout,
 	       buf, timeout/HZ, tgid, task->comm);
 
 	entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries),
-			  GFP_KERNEL);
+			  GFP_ATOMIC);
 	if (!entries)
 		return;
 	nr_entries = stack_trace_save_tsk(task, entries,
@@ -4176,7 +4182,8 @@ static void warn_freeze_timeout(struct cgroup *cgrp, int timeout)
 		css_task_iter_end(&it);
 	}
 
-	buf = kmalloc(PATH_MAX, GFP_KERNEL);
+	/* still under rcu_read_lock() from guard(rcu)() above */
+	buf = kmalloc(PATH_MAX, GFP_ATOMIC);
 	if (!buf)
 		return;
 


More information about the Devel mailing list