Cgroup-v2 implementation of freezer ignores kernel threads, but still
counts them against nr_frozen_tasks. So the cgroup with kthread inside
will never report frozen.

In VZ containers we have "umh" and "kthreadd" kthreads in each container
and we put them into container cgroups so that they share container
resource limits. So container cgroups are virtually unfreezable.

To make container cgroups freezable, let's count the number of kthreads
in each cgroup, and offset nr_frozen_tasks checks with it. This way we
can ignore kthreads completely and report cgroup frozen when all
non-kthread tasks are frozen.

Note: nr_kthreads is protected with css_set_lock.

https://virtuozzo.atlassian.net/browse/VSTOR-118578
Signed-off-by: Pavel Tikhomirov <[email protected]>

Feature: cgroup/freeze: improvements
---
 include/linux/cgroup-defs.h |  5 +++++
 kernel/cgroup/cgroup.c      | 23 +++++++++++++++++++++++
 kernel/cgroup/freezer.c     |  3 ++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 99979c8a06cfe..d68fca31e6e65 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -419,6 +419,11 @@ struct cgroup_freezer_state {
         * frozen, SIGSTOPped, and PTRACEd.
         */
        int nr_frozen_tasks;
+
+       /*
+        * Number of kernel threads in this cgroup
+        */
+       int nr_kthreads;
 };
 
 struct cgroup {
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 8e22aea876505..2f7db20f8a460 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -889,6 +889,23 @@ static void css_set_skip_task_iters(struct css_set *cset,
                css_task_iter_skip(it, task);
 }
 
+/*
+ * Increment cgroup's nr_kthreads.
+ */
+static inline void cgroup_inc_kthread_cnt(struct cgroup *cgrp)
+{
+       cgrp->freezer.nr_kthreads++;
+}
+
+/*
+ * Decrement cgroup's nr_kthreads.
+ */
+static inline void cgroup_dec_kthread_cnt(struct cgroup *cgrp)
+{
+       cgrp->freezer.nr_kthreads--;
+       WARN_ON_ONCE(cgrp->freezer.nr_kthreads < 0);
+}
+
 /**
  * css_set_move_task - move a task from one css_set to another
  * @task: task being moved
@@ -935,7 +952,13 @@ static void css_set_move_task(struct task_struct *task,
                cgroup_move_task(task, to_cset);
                list_add_tail(&task->cg_list, use_mg_tasks ? &to_cset->mg_tasks 
:
                                                             &to_cset->tasks);
+
+               if (task->flags & PF_KTHREAD)
+                       cgroup_inc_kthread_cnt(to_cset->dfl_cgrp);
        }
+
+       if (from_cset && (task->flags & PF_KTHREAD))
+               cgroup_dec_kthread_cnt(from_cset->dfl_cgrp);
 }
 
 /*
diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
index 617861a547935..a2d9e55257bcc 100644
--- a/kernel/cgroup/freezer.c
+++ b/kernel/cgroup/freezer.c
@@ -61,7 +61,8 @@ void cgroup_update_frozen(struct cgroup *cgrp)
         * the cgroup frozen. Otherwise it's not frozen.
         */
        frozen = test_bit(CGRP_FREEZE, &cgrp->flags) &&
-               cgrp->freezer.nr_frozen_tasks == __cgroup_task_count(cgrp);
+               cgrp->freezer.nr_frozen_tasks + cgrp->freezer.nr_kthreads ==
+               __cgroup_task_count(cgrp);
 
        if (frozen) {
                /* Already there? */
-- 
2.51.1

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to