Skip to content

Commit ee1251f

Browse files
Chen Ridonghtejun
authored andcommitted
cgroup/freezer: Reduce redundant traversal for cgroup_freeze
Whether a cgroup is frozen is determined solely by whether it is set to to be frozen and whether its parent is frozen. Currently, when is cgroup is frozen or unfrozen, it iterates through the entire subtree to freeze or unfreeze its descentdants. However, this is unesessary for a cgroup that does not change its effective frozen status. This path aims to skip the subtree if its parent does not have a change in effective freeze. For an example, subtree like, a-b-c-d-e-f-g, when a is frozen, the entire tree is frozen. If we freeze b and c again, it is unesessary to iterate d, e, f and g. So does that If we unfreeze b/c. Reviewed-by: Michal Koutný <mkoutny@suse.com> Signed-off-by: Chen Ridong <chenridong@huawei.com> Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent 2190df6 commit ee1251f

2 files changed

Lines changed: 15 additions & 17 deletions

File tree

include/linux/cgroup-defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ struct cgroup_freezer_state {
398398
bool freeze;
399399

400400
/* Should the cgroup actually be frozen? */
401-
int e_freeze;
401+
bool e_freeze;
402402

403403
/* Fields below are protected by css_set_lock */
404404

kernel/cgroup/freezer.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,10 @@ void cgroup_freezer_migrate_task(struct task_struct *task,
260260
void cgroup_freeze(struct cgroup *cgrp, bool freeze)
261261
{
262262
struct cgroup_subsys_state *css;
263+
struct cgroup *parent;
263264
struct cgroup *dsct;
264265
bool applied = false;
266+
bool old_e;
265267

266268
lockdep_assert_held(&cgroup_mutex);
267269

@@ -282,22 +284,18 @@ void cgroup_freeze(struct cgroup *cgrp, bool freeze)
282284
if (cgroup_is_dead(dsct))
283285
continue;
284286

285-
if (freeze) {
286-
dsct->freezer.e_freeze++;
287-
/*
288-
* Already frozen because of ancestor's settings?
289-
*/
290-
if (dsct->freezer.e_freeze > 1)
291-
continue;
292-
} else {
293-
dsct->freezer.e_freeze--;
294-
/*
295-
* Still frozen because of ancestor's settings?
296-
*/
297-
if (dsct->freezer.e_freeze > 0)
298-
continue;
299-
300-
WARN_ON_ONCE(dsct->freezer.e_freeze < 0);
287+
/*
288+
* e_freeze is affected by parent's e_freeze and dst's freeze.
289+
* If old e_freeze eq new e_freeze, no change, its children
290+
* will not be affected. So do nothing and skip the subtree
291+
*/
292+
old_e = dsct->freezer.e_freeze;
293+
parent = cgroup_parent(dsct);
294+
dsct->freezer.e_freeze = (dsct->freezer.freeze ||
295+
parent->freezer.e_freeze);
296+
if (dsct->freezer.e_freeze == old_e) {
297+
css = css_rightmost_descendant(css);
298+
continue;
301299
}
302300

303301
/*

0 commit comments

Comments
 (0)