The commit is pushed to "branch-rh10-6.12.0-55.13.1.2.x.vz10-ovz" and will
appear at [email protected]:openvz/vzkernel.git
after rh10-6.12.0-55.13.1.2.18.vz10
------>
commit 2b16bcfc28fc704da99f56f6b868a07d5be874eb
Author: Pavel Tikhomirov <[email protected]>
Date: Wed Nov 19 11:36:45 2025 +0800
cgroup-v2/freezer: Print information about unfreezable process
We already had this feature in cgroup-v1 freezer, so let's also have it
for cgroup-v2. Difference in cgroup-v2 freezer is that there is no loop
over tasks like in freezer_read() -> update_if_frozen(),
cgroup_events_show() only checks CGRP_FROZEN flag, so we have to
add our own loop over each descendant css and each task in it.
Note: freeze_jiffies is protected with css_set_lock together with
CGRP_FREEZE bit.
https://virtuozzo.atlassian.net/browse/VSTOR-118578
Signed-off-by: Pavel Tikhomirov <[email protected]>
Feature: cgroup/freeze: enhance logging
---
include/linux/cgroup-defs.h | 5 +++
include/linux/cgroup.h | 3 ++
kernel/cgroup/cgroup.c | 97 ++++++++++++++++++++++++++++++++++++++++++
kernel/cgroup/freezer.c | 8 +++-
kernel/cgroup/legacy_freezer.c | 36 +---------------
5 files changed, 112 insertions(+), 37 deletions(-)
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index d68fca31e6e65..d8c489a408815 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -424,6 +424,11 @@ struct cgroup_freezer_state {
* Number of kernel threads in this cgroup
*/
int nr_kthreads;
+
+ /*
+ * Jiffies of last freeze
+ */
+ u64 freeze_jiffies;
};
struct cgroup {
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 86ee6604a5207..2e01e484cbac7 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -876,4 +876,7 @@ struct cgroup *task_get_cgroup1(struct task_struct *tsk,
int hierarchy_id);
struct cgroup_of_peak *of_peak(struct kernfs_open_file *of);
+void warn_freeze_timeout_task(struct cgroup *cgrp, int timeout,
+ struct task_struct *task);
+
#endif /* _LINUX_CGROUP_H */
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 2f7db20f8a460..561fab2179d24 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -61,6 +61,9 @@
#include <linux/psi.h>
#include <net/sock.h>
#include <linux/task_work.h>
+#include <linux/ratelimit.h>
+#include <linux/stacktrace.h>
+#include <linux/sysctl.h>
#include <linux/ve.h>
#define CREATE_TRACE_POINTS
@@ -4099,6 +4102,98 @@ static ssize_t cgroup_max_depth_write(struct
kernfs_open_file *of,
return nbytes;
}
+#define MAX_STACK_TRACE_DEPTH 64
+
+void warn_freeze_timeout_task(struct cgroup *cgrp, int timeout,
+ struct task_struct *task)
+{
+ char *buf __free(kfree) = NULL;
+ unsigned long *entries __free(kfree) = NULL;
+ unsigned long nr_entries, i;
+ pid_t tgid;
+
+ buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ if (cgroup_path(cgrp, buf, PATH_MAX) < 0)
+ return;
+
+ tgid = task_pid_nr_ns(task, &init_pid_ns);
+ printk(KERN_WARNING "Freeze of %s took %d sec, "
+ "due to unfreezable process %d:%s, stack:\n",
+ buf, timeout/HZ, tgid, task->comm);
+
+ entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries),
+ GFP_KERNEL);
+ if (!entries)
+ return;
+ nr_entries = stack_trace_save_tsk(task, entries,
+ MAX_STACK_TRACE_DEPTH, 0);
+ for (i = 0; i < nr_entries; i++)
+ printk(KERN_WARNING "[<%pK>] %pB\n",
+ (void *)entries[i], (void *)entries[i]);
+}
+
+static void warn_freeze_timeout(struct cgroup *cgrp, int timeout)
+{
+ struct cgroup_subsys_state *css;
+ char *buf __free(kfree) = NULL;
+
+ guard(rcu)();
+ css_for_each_descendant_post(css, &cgrp->self) {
+ struct task_struct *task;
+ struct css_task_iter it;
+
+ css_task_iter_start(css, 0, &it);
+ while ((task = css_task_iter_next(&it))) {
+ if (task->flags & PF_KTHREAD)
+ continue;
+ if (task->frozen)
+ continue;
+
+ warn_freeze_timeout_task(cgrp, timeout, task);
+ css_task_iter_end(&it);
+ return;
+ }
+ css_task_iter_end(&it);
+ }
+
+ buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ if (cgroup_path(cgrp, buf, PATH_MAX) < 0)
+ return;
+
+ printk(KERN_WARNING "Freeze of %s took %d sec, "
+ "but no unfreezable process detected\n", buf, timeout/HZ);
+}
+
+static void check_freeze_timeout(struct cgroup *cgrp)
+{
+ static DEFINE_RATELIMIT_STATE(freeze_timeout_rs,
+ DEFAULT_FREEZE_TIMEOUT, 1);
+ u64 freeze_jiffies;
+ int timeout;
+
+ scoped_guard(spinlock, &css_set_lock) {
+ if (!test_bit(CGRP_FREEZE, &cgrp->flags) ||
+ test_bit(CGRP_FROZEN, &cgrp->flags))
+ return;
+ freeze_jiffies = READ_ONCE(cgrp->freezer.freeze_jiffies);
+ }
+
+ timeout = READ_ONCE(sysctl_freeze_timeout);
+ if (!freeze_jiffies || time_is_after_jiffies64(freeze_jiffies +
timeout))
+ return;
+
+ if (!__ratelimit(&freeze_timeout_rs))
+ return;
+
+ warn_freeze_timeout(cgrp, timeout);
+}
+
static int cgroup_events_show(struct seq_file *seq, void *v)
{
struct cgroup *cgrp = seq_css(seq)->cgroup;
@@ -4106,6 +4201,8 @@ static int cgroup_events_show(struct seq_file *seq, void
*v)
seq_printf(seq, "populated %d\n", cgroup_is_populated(cgrp));
seq_printf(seq, "frozen %d\n", test_bit(CGRP_FROZEN, &cgrp->flags));
+ check_freeze_timeout(cgrp);
+
return 0;
}
diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
index a2d9e55257bcc..e6ef44d0ab4a8 100644
--- a/kernel/cgroup/freezer.c
+++ b/kernel/cgroup/freezer.c
@@ -3,6 +3,7 @@
#include <linux/sched.h>
#include <linux/sched/task.h>
#include <linux/sched/signal.h>
+#include <linux/jiffies.h>
#include "cgroup-internal.h"
@@ -183,10 +184,13 @@ static void cgroup_do_freeze(struct cgroup *cgrp, bool
freeze)
lockdep_assert_held(&cgroup_mutex);
spin_lock_irq(&css_set_lock);
- if (freeze)
+ if (freeze) {
set_bit(CGRP_FREEZE, &cgrp->flags);
- else
+ cgrp->freezer.freeze_jiffies = get_jiffies_64();
+ } else {
clear_bit(CGRP_FREEZE, &cgrp->flags);
+ cgrp->freezer.freeze_jiffies = 0;
+ }
spin_unlock_irq(&css_set_lock);
if (freeze)
diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c
index b048f6b530688..a59e5a14f45ed 100644
--- a/kernel/cgroup/legacy_freezer.c
+++ b/kernel/cgroup/legacy_freezer.c
@@ -25,7 +25,6 @@
#include <linux/cpu.h>
#include <linux/jiffies.h>
#include <linux/ratelimit.h>
-#include <linux/stacktrace.h>
#include <linux/sysctl.h>
/*
@@ -244,11 +243,6 @@ static void check_freezer_timeout(struct
cgroup_subsys_state *css,
DEFAULT_FREEZE_TIMEOUT, 1);
int __freeze_timeout = READ_ONCE(sysctl_freeze_timeout);
struct freezer *freezer = css_freezer(css);
- unsigned long nr_entries;
- unsigned long *entries;
- char *freezer_cg_name;
- pid_t tgid;
- int i;
if (!freezer->freeze_jiffies ||
freezer->freeze_jiffies + __freeze_timeout > get_jiffies_64())
@@ -257,35 +251,7 @@ static void check_freezer_timeout(struct
cgroup_subsys_state *css,
if (!__ratelimit(&freeze_timeout_rs))
return;
- freezer_cg_name = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!freezer_cg_name)
- return;
-
- if (cgroup_path(css->cgroup, freezer_cg_name, PATH_MAX) < 0)
- goto free_cg_name;
-
- tgid = task_pid_nr_ns(task, &init_pid_ns);
-
- printk(KERN_WARNING "Freeze of %s took %d sec, "
- "due to unfreezable process %d:%s, stack:\n",
- freezer_cg_name, __freeze_timeout/HZ, tgid, task->comm);
-
- entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries),
- GFP_KERNEL);
- if (!entries)
- goto free_cg_name;
-
- nr_entries = stack_trace_save_tsk(task, entries,
- MAX_STACK_TRACE_DEPTH, 0);
-
- for (i = 0; i < nr_entries; i++) {
- printk(KERN_WARNING "[<%pK>] %pB\n",
- (void *)entries[i], (void *)entries[i]);
- }
-
- kfree(entries);
-free_cg_name:
- kfree(freezer_cg_name);
+ warn_freeze_timeout_task(css->cgroup, __freeze_timeout, task);
}
/**
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel