cgroup: make control mask updates modular and recursive
Tejun Heo
maintainerPATCH 1/1 cgroup: make control mask updates modular and recursive
Hello,
Currently, subsystem enabling and disabling in the default hierarchy are implemented as a long chain of interdependent operations in cgroup_subtree_control_write(). The function calculates what need to be done to its children and excute the necessary operations. The function unfortunately ends up being a rather opaque blob of operations which is difficult to wrap one's head around or reuse.
This patchset restructures control mask update so that it's composed of discrete idempotent and recursive operations. While no new features are added by this patchset, future changes will make use of flexible control mask updates to implement features involving more complex controller management.
This patchset includes the following 12 patches.
0001-cgroup-separate-out-interface-file-creation-from-css.patch 0002-cgroup-explicitly-track-whether-a-cgroup_subsys_stat.patch 0003-cgroup-reorder-operations-in-cgroup_mkdir.patch 0004-cgroup-factor-out-cgroup_create-out-of-cgroup_mkdir.patch 0005-cgroup-introduce-cgroup_control-and-cgroup_ss_mask.patch 0006-cgroup-factor-out-cgroup_drain_offline-from-cgroup_s.patch 0007-cgroup-factor-out-cgroup_apply_control_disable-from-.patch 0008-cgroup-factor-out-cgroup_apply_control_enable-from-c.patch 0009-cgroup-make-cgroup_drain_offline-and-cgroup_apply_co.patch 0010-cgroup-introduce-cgroup_-save-propagate-restore-_con.patch 0011-cgroup-Factor-out-cgroup_-apply-finalize-_control-fr.patch 0012-cgroup-make-cgroup_calc_subtree_ss_mask-take-this_ss.patch
The patchset is on top of cgroup/for-4.6 6e5c830770f ("cgroup: make cgroup subsystem masks u16") and available in the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-recursive-control
diffstat follows. Thanks.
include/linux/cgroup-defs.h | 3 kernel/cgroup.c | 653 ++++++++++++++++++++++++++++---------------- 2 files changed, 419 insertions(+), 237 deletions(-)
--
tejun
Tejun Heo
maintainerPATCH 1/12 cgroup: separate out interface file creation from css creation
Currently, interface files are created when a css is created depending on whether @visible is set. This patch separates out the two into separate steps to help code refactoring and eventually allow cgroups which aren't visible through cgroup fs.
Move css_populate_dir() out of create_css() and drop @visible. While at it, rename the function to css_create() for consistency.
--- kernel/cgroup.c | 72 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 29 deletions(-)
kernel/cgroup.c +43 -29
@@ -222,8 +222,8 @@ static struct cftype cgroup_legacy_base_files[];static int rebind_subsystems (struct cgroup_root *dst_root,u16 ss_mask);static void css_task_iter_advance (struct css_task_iter *it);static int cgroup_destroy_locked (struct cgroup *cgrp); -static int create_css (struct cgroup *cgrp,struct cgroup_subsys *ss, -bool visible); +static struct cgroup_subsys_state *css_create (struct cgroup *cgrp, +struct cgroup_subsys *ss);static void css_release (struct percpu_ref *ref);static void kill_css (struct cgroup_subsys_state *css); static int cgroup_addrm_files(struct cgroup_subsys_state *css,
@@ -3081,14 +3081,26 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,*/ do_each_subsys_mask(ss, ssid, enable) {cgroup_for_each_live_child (child, cgrp) { -if (css_enable & (1 << ssid)) - ret =create_css (child, ss, - cgrp->subtree_control & (1 << ssid)); -else +if (css_enable & (1 << ssid)) { +struct cgroup_subsys_state *css; + + css =css_create (child, ss); +if (IS_ERR (css)) { + ret =PTR_ERR (css); + goto err_undo_css; + } + +if (cgrp->subtree_control & (1 << ssid)) { + ret =css_populate_dir (css,NULL ); +if (ret) + goto err_undo_css; + } + }else { ret =css_populate_dir (cgroup_css (child, ss),NULL ); -if (ret) - goto err_undo_css; +if (ret) + goto err_undo_css; + } } }while_each_subsys_mask ();
@@ -4716,7 +4728,9 @@ static void css_release_work_fn(struct work_struct *work)* Those are supported by RCU protecting clearing of * cgrp->kn->priv backpointer. */ -RCU_INIT_POINTER (*(void __rcu __force **)&cgrp->kn->priv,NULL ); +if (cgrp->kn) +RCU_INIT_POINTER (*(void __rcu __force **)&cgrp->kn->priv, +NULL ); }mutex_unlock (&cgroup_mutex);
@@ -4797,17 +4811,16 @@ static void offline_css(struct cgroup_subsys_state *css) }/** -* create_css - create a cgroup_subsys_state +* css_create - create a cgroup_subsys_state * @cgrp: the cgroup new css will be associated with * @ss: the subsys of new css -* @visible: whether to create control knobs for the new css or not * * Create a new css associated with @cgrp - @ss pair. On success, the new -* css is online and installed in @cgrp with all interface files created if -* @visible. Returns 0 on success, -errno on failure. +* css is online and installed in @cgrp. This function doesn't create the +* interface files. Returns 0 on success, -errno on failure. */ -static int create_css (struct cgroup *cgrp,struct cgroup_subsys *ss, -bool visible) +static struct cgroup_subsys_state *css_create (struct cgroup *cgrp, +struct cgroup_subsys *ss) {struct cgroup *parent =cgroup_parent (cgrp);struct cgroup_subsys_state *parent_css =cgroup_css (parent, ss);
@@ -4818,7 +4831,7 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss, css = ss->css_alloc (parent_css);if (IS_ERR (css)) -return PTR_ERR (css); +return css;init_and_link_css (css, ss, cgrp);
@@ -4831,12 +4844,6 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss, goto err_free_percpu_ref; css->id = err; -if (visible) { - err =css_populate_dir (css,NULL ); -if (err) - goto err_free_id; - } -/* @css is ready to be brought online now, make it visible */ list_add_tail_rcu (&css->sibling, &parent_css->children);cgroup_idr_replace (&ss->css_idr, css, css->id);
@@ -4854,18 +4861,16 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss, ss->warned_broken_hierarchy = true; } -return 0 ; +return css; err_list_del:list_del_rcu (&css->sibling); -css_clear_dir (css,NULL ); -err_free_id:cgroup_idr_remove (&ss->css_idr, css->id); err_free_percpu_ref:percpu_ref_exit (&css->refcnt); err_free_css:call_rcu (&css->rcu_head, css_free_rcu_fn); -return err; +return ERR_PTR (err); } static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
@@ -4962,10 +4967,19 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,/* let's create and online css's */ do_each_subsys_mask(ss, ssid, parent->subtree_ss_mask) { - ret =create_css (cgrp, ss, - parent->subtree_control & (1 << ssid)); -if (ret) +struct cgroup_subsys_state *css; + + css =css_create (cgrp, ss); +if (IS_ERR (css)) { + ret =PTR_ERR (css); goto out_destroy; + } + +if (parent->subtree_control & (1 << ssid)) { + ret =css_populate_dir (css,NULL ); +if (ret) + goto out_destroy; + } }while_each_subsys_mask ();/*
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 2/12 cgroup: explicitly track whether a cgroup_subsys_state is visible to userland
In reply to Tejun HeoCurrently, whether a css (cgroup_subsys_state) has its interface files created is not tracked and assumed to change together with the owning cgroup's lifecycle. cgroup directory and interface creation is being separated out from internal object creation to help refactoring and eventually allow cgroups which are not visible through cgroupfs.
This patch adds CSS_VISIBLE to track whether a css has its interface files created and perform management operations only when necessary which helps decoupling interface file handling from internal object lifecycle. After this patch, all css interface file management functions can be called regardless of the current state and will achieve the expected result.
--- include/linux/cgroup-defs.h | 1 + kernel/cgroup.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)
include/linux/cgroup-defs.h +1 -0
@@ -45,6 +45,7 @@ enum {CSS_NO_REF = (1 <<0 ),/* no reference counting for this css */ CSS_ONLINE = (1 <<1 ),/* between ->css_online() and ->css_offline() */ CSS_RELEASED = (1 <<2 ),/* refcnt reached zero, released */ + CSS_VISIBLE = (1 << 3), /* css is visible to userland */ };/* bits in struct cgroup flags field */
kernel/cgroup.c +12 -1
@@ -1420,6 +1420,11 @@ static void css_clear_dir(struct cgroup_subsys_state *css,struct cgroup *cgrp = cgrp_override ?: css->cgroup;struct cftype *cfts; +if (!(css->flags &CSS_VISIBLE )) +return ; + + css->flags &= ~CSS_VISIBLE ; +list_for_each_entry (cfts, &css->ss->cfts, node)cgroup_addrm_files (css, cgrp, cfts, false); }
@@ -1438,6 +1443,9 @@ static int css_populate_dir(struct cgroup_subsys_state *css,struct cftype *cfts, *failed_cfts;int ret; +if (css->flags &CSS_VISIBLE ) +return 0 ; +if (!css->ss) {if (cgroup_on_dfl (cgrp)) cfts = cgroup_dfl_base_files;
@@ -1454,6 +1462,9 @@ static int css_populate_dir(struct cgroup_subsys_state *css, goto err; } } + + css->flags |=CSS_VISIBLE ; +return 0 ; err:list_for_each_entry (cfts, &css->ss->cfts, node) {
@@ -3402,7 +3413,7 @@ static int cgroup_apply_cftypes(struct cftype *cfts, bool is_add)css_for_each_descendant_pre (css,cgroup_css (root, ss)) {struct cgroup *cgrp = css->cgroup; -if (cgroup_is_dead (cgrp)) +if (!(css->flags &CSS_VISIBLE ))continue ; ret =cgroup_addrm_files (css, cgrp, cfts, is_add);
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 3/12 cgroup: reorder operations in cgroup_mkdir()
In reply to Tejun HeoCurrently, operations to initialize internal objects and create interface directory and files are intermixed in cgroup_mkdir(). We're in the process of refactoring cgroup and css management paths to separate them out to eventually allow cgroups which aren't visible through cgroup fs.
This patch reorders operations inside cgroup_mkdir() so that interface directory and file handling comes after internal object initialization. This will enable further refactoring.
--- kernel/cgroup.c | 61 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 31 deletions(-)
kernel/cgroup.c +30 -31
@@ -4941,20 +4941,6 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,if (test_bit (CGRP_CPUSET_CLONE_CHILDREN , &parent->flags))set_bit (CGRP_CPUSET_CLONE_CHILDREN , &cgrp->flags); -/* create the directory */ - kn =kernfs_create_dir (parent->kn, name, mode, cgrp); -if (IS_ERR (kn)) { - ret =PTR_ERR (kn); - goto out_free_id; - } - cgrp->kn = kn; - -/* -* This extra ref will be put in cgroup_free_fn() and guarantees -* that @cgrp->kn is always accessible. -*/ -kernfs_get (kn); - cgrp->self.serial_nr = css_serial_nr_next++;/* allocation complete, commit to creation */
@@ -4968,15 +4954,7 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,*/ cgroup_idr_replace (&root->cgroup_idr, cgrp, cgrp->id); - ret =cgroup_kn_set_ugid (kn); -if (ret) - goto out_destroy; - - ret =css_populate_dir (&cgrp->self,NULL ); -if (ret) - goto out_destroy; - -/* let's create and online css's */ +/* create the csses */ do_each_subsys_mask(ss, ssid, parent->subtree_ss_mask) {struct cgroup_subsys_state *css;
@@ -4985,12 +4963,6 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, ret =PTR_ERR (css); goto out_destroy; } - -if (parent->subtree_control & (1 << ssid)) { - ret =css_populate_dir (css,NULL ); -if (ret) - goto out_destroy; - } }while_each_subsys_mask ();/*
@@ -5002,13 +4974,40 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,cgroup_refresh_subtree_ss_mask (cgrp); } +/* create the directory */ + kn =kernfs_create_dir (parent->kn, name, mode, cgrp); +if (IS_ERR (kn)) { + ret =PTR_ERR (kn); + goto out_destroy; + } + cgrp->kn = kn; + +/* +* This extra ref will be put in cgroup_free_fn() and guarantees +* that @cgrp->kn is always accessible. +*/ +kernfs_get (kn); + + ret =cgroup_kn_set_ugid (kn); +if (ret) + goto out_destroy; + + ret =css_populate_dir (&cgrp->self,NULL ); +if (ret) + goto out_destroy; + + do_each_subsys_mask(ss, ssid, parent->subtree_control) { + ret =css_populate_dir (cgroup_css (cgrp, ss),NULL ); +if (ret) + goto out_destroy; + }while_each_subsys_mask (); + +/* let's create and online css's */ kernfs_activate (kn); ret =0 ; goto out_unlock; -out_free_id: -cgroup_idr_remove (&root->cgroup_idr, cgrp->id); out_cancel_ref:percpu_ref_exit (&cgrp->self.refcnt); out_free_cgrp:
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 4/12 cgroup: factor out cgroup_create() out of cgroup_mkdir()
In reply to Tejun HeoWe're in the process of refactoring cgroup and css management paths to separate them out to eventually allow cgroups which aren't visible through cgroup fs. This patch factors out cgroup_create() out of cgroup_mkdir(). cgroup_create() contains all internal object creation and initialization. cgroup_mkdir() uses cgroup_create() to create the internal cgroup and adds interface directory and file creation.
This patch doesn't cause any behavior differences.
--- kernel/cgroup.c | 72 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 29 deletions(-)
kernel/cgroup.c +43 -29
@@ -4884,33 +4884,19 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,return ERR_PTR (err); } -static int cgroup_mkdir (struct kernfs_node *parent_kn,const char *name, -umode_t mode) +static struct cgroup *cgroup_create (struct cgroup *parent) { -struct cgroup *parent, *cgrp, *tcgrp; -struct cgroup_root *root; +struct cgroup_root *root = parent->root;struct cgroup_subsys *ss; -struct kernfs_node *kn; -int level, ssid, ret; - -/* Do not accept '\n' to prevent making /proc/<pid>/cgroup unparsable. -*/ -if (strchr (name,'\n' )) -return -EINVAL ; - - parent =cgroup_kn_lock_live (parent_kn); -if (!parent) -return -ENODEV ; - root = parent->root; - level = parent->level +1 ; +struct cgroup *cgrp, *tcgrp; +int level = parent->level +1 ; +int ssid, ret;/* allocate the cgroup and its ID, 0 is reserved for the root */ cgrp =kzalloc (sizeof (*cgrp) +sizeof (cgrp->ancestor_ids[0 ]) * (level +1 ),GFP_KERNEL ); -if (!cgrp) { - ret = -ENOMEM ; - goto out_unlock; - } +if (!cgrp) +return ERR_PTR (-ENOMEM ); ret =percpu_ref_init (&cgrp->self.refcnt, css_release,0 ,GFP_KERNEL );if (ret)
@@ -4974,6 +4960,40 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,cgroup_refresh_subtree_ss_mask (cgrp); } +return cgrp; + +out_cancel_ref: +percpu_ref_exit (&cgrp->self.refcnt); +out_free_cgrp: +kfree (cgrp); +return ERR_PTR (ret); +out_destroy: +cgroup_destroy_locked (cgrp); +return ERR_PTR (ret); +} + +static int cgroup_mkdir (struct kernfs_node *parent_kn,const char *name, +umode_t mode) +{ +struct cgroup *parent, *cgrp; +struct cgroup_subsys *ss; +struct kernfs_node *kn; +int ssid, ret; + +/* do not accept '\n' to prevent making /proc/<pid>/cgroup unparsable */ +if (strchr (name,'\n' )) +return -EINVAL ; + + parent =cgroup_kn_lock_live (parent_kn); +if (!parent) +return -ENODEV ; + + cgrp =cgroup_create (parent); +if (IS_ERR (cgrp)) { + ret =PTR_ERR (cgrp); + goto out_unlock; + } +/* create the directory */ kn =kernfs_create_dir (parent->kn, name, mode, cgrp);if (IS_ERR (kn)) {
@@ -5008,17 +5028,11 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, ret =0 ; goto out_unlock; -out_cancel_ref: -percpu_ref_exit (&cgrp->self.refcnt); -out_free_cgrp: -kfree (cgrp); +out_destroy: +cgroup_destroy_locked (cgrp); out_unlock:cgroup_kn_unlock (parent_kn);return ret; - -out_destroy: -cgroup_destroy_locked (cgrp); - goto out_unlock; }/*
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 5/12 cgroup: introduce cgroup_control() and cgroup_ss_mask()
In reply to Tejun HeoWhen a controller is enabled and visible on a non-root cgroup is determined by subtree_control and subtree_ss_mask of the parent cgroup. For a root cgroup, by the type of the hierarchy and which controllers are attached to it. Deciding the above on each usage is fragile and unnecessarily complicates the users.
This patch introduces cgroup_control() and cgroup_ss_mask() which calculate and return the [visibly] enabled subsyste mask for the specified cgroup and conver the existing usages.
* cgroup_e_css() is restructured for simplicity.
* cgroup_calc_subtree_ss_mask() no longer needs to distinguish root and non-root cases.
* With cgroup_control(), cgroup_controllers_show() can now handle both root and non-root cases. cgroup_root_controllers_show() is removed.
--- kernel/cgroup.c | 63 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 31 deletions(-)
kernel/cgroup.c +32 -31
@@ -346,6 +346,28 @@ static struct cgroup *cgroup_parent(struct cgroup *cgrp)return NULL ; } +/* subsystems visibly enabled on a cgroup */ +static u16 cgroup_control (struct cgroup *cgrp) +{ +struct cgroup *parent =cgroup_parent (cgrp); + +if (!parent) +return cgrp->root->subsys_mask & ~cgrp_dfl_root_inhibit_ss_mask; + +return parent->subtree_control; +} + +/* subsystems enabled on a cgroup */ +static u16 cgroup_ss_mask (struct cgroup *cgrp) +{ +struct cgroup *parent =cgroup_parent (cgrp); + +if (!parent) +return cgrp->root->subsys_mask; + +return parent->subtree_ss_mask; +} +/** * cgroup_css - obtain a cgroup's css for the specified subsystem * @cgrp: the cgroup of interest
@@ -385,16 +407,15 @@ static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp,if (!ss)return &cgrp->self; -if (!(cgrp->root->subsys_mask & (1 << ss->id))) -return NULL ; -/* * This function is used while updating css associations and thus -* can't test the csses directly. Use ->subtree_ss_mask. +* can't test the csses directly. Test ss_mask. */ -while (cgroup_parent (cgrp) && - !(cgroup_parent (cgrp)->subtree_ss_mask & (1 << ss->id))) +while (!(cgroup_ss_mask (cgrp) & (1 << ss->id))) { cgrp =cgroup_parent (cgrp); +if (!cgrp) +return NULL ; + }return cgroup_css (cgrp, ss); }
@@ -1275,7 +1296,6 @@ static umode_t cgroup_file_mode(const struct cftype *cft)*/ static u16 cgroup_calc_subtree_ss_mask (struct cgroup *cgrp,u16 subtree_control) { -struct cgroup *parent =cgroup_parent (cgrp);u16 cur_ss_mask = subtree_control;struct cgroup_subsys *ss;int ssid;
@@ -1297,10 +1317,7 @@ static u16 cgroup_calc_subtree_ss_mask(struct cgroup *cgrp, u16 subtree_control)* happen only if some depended-upon subsystems were bound * to non-default hierarchies. */ -if (parent) - new_ss_mask &= parent->subtree_ss_mask; -else - new_ss_mask &= cgrp->root->subsys_mask; + new_ss_mask &=cgroup_ss_mask (cgrp);if (new_ss_mask == cur_ss_mask)break ;
@@ -2863,22 +2880,12 @@ static void cgroup_print_ss_mask(struct seq_file *seq, u16 ss_mask)seq_putc (seq,'\n' ); } -/* show controllers which are currently attached to the default hierarchy */ -static int cgroup_root_controllers_show (struct seq_file *seq,void *v) -{ -struct cgroup *cgrp =seq_css (seq)->cgroup; - -cgroup_print_ss_mask (seq, cgrp->root->subsys_mask & - ~cgrp_dfl_root_inhibit_ss_mask); -return 0 ; -} -/* show controllers which are enabled from the parent */ static int cgroup_controllers_show (struct seq_file *seq,void *v) {struct cgroup *cgrp =seq_css (seq)->cgroup; -cgroup_print_ss_mask (seq,cgroup_parent (cgrp)->subtree_control); +cgroup_print_ss_mask (seq,cgroup_control (cgrp));return 0 ; }
@@ -4565,12 +4572,6 @@ static struct cftype cgroup_dfl_base_files[] = { }, { .name = "cgroup.controllers", - .flags = CFTYPE_ONLY_ON_ROOT, - .seq_show = cgroup_root_controllers_show, - }, - { - .name = "cgroup.controllers", - .flags = CFTYPE_NOT_ON_ROOT, .seq_show = cgroup_controllers_show, }, {
@@ -4941,7 +4942,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent)cgroup_idr_replace (&root->cgroup_idr, cgrp, cgrp->id);/* create the csses */ - do_each_subsys_mask(ss, ssid, parent->subtree_ss_mask) { + do_each_subsys_mask(ss, ssid, cgroup_ss_mask(cgrp)) {struct cgroup_subsys_state *css; css =css_create (cgrp, ss);
@@ -4956,7 +4957,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent)* subtree_control from the parent. Each is configured manually. */ if (!cgroup_on_dfl (cgrp)) { - cgrp->subtree_control = parent->subtree_control; + cgrp->subtree_control =cgroup_control (cgrp);cgroup_refresh_subtree_ss_mask (cgrp); }
@@ -5016,7 +5017,7 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,if (ret) goto out_destroy; - do_each_subsys_mask(ss, ssid, parent->subtree_control) { + do_each_subsys_mask(ss, ssid, cgroup_control(cgrp)) { ret =css_populate_dir (cgroup_css (cgrp, ss),NULL );if (ret) goto out_destroy;
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 6/12 cgroup: factor out cgroup_drain_offline() from cgroup_subtree_control_write()
In reply to Tejun HeoFactor out async css offline draining into cgroup_drain_offline().
* Nest subsystem walk inside child walk. The child walk will later be converted to subtree walk which is a bit more expensive.
* Relocate the draining above subsystem mask preparation, which doesn't create any behavior differences but helps further refactoring.
--- kernel/cgroup.c | 77 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 25 deletions(-)
kernel/cgroup.c +52 -25
@@ -2960,6 +2960,53 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)return ret; } +/** +* cgroup_drain_offline - wait for previously offlined csses to go away +* @cgrp: parent of the target cgroups +* +* Because css offlining is asynchronous, userland may try to re-enable a +* controller while the previous css is still around. This function drains +* the previous css instances of @cgrp's children. +* +* Must be called with cgroup_mutex held. Returns %false if there were no +* dying css instances. Returns %true if there were one or more and this +* function waited. On %true return, cgroup_mutex has been dropped and +* re-acquired inbetween which anything could have happened. The caller +* typically would have to start over. +*/ +static bool cgroup_drain_offline (struct cgroup *cgrp) +{ +struct cgroup *dsct; +struct cgroup_subsys *ss; +int ssid; + +lockdep_assert_held (&cgroup_mutex); + +cgroup_for_each_live_child (dsct, cgrp) { +for_each_subsys (ss, ssid) { +struct cgroup_subsys_state *css =cgroup_css (dsct, ss); +DEFINE_WAIT (wait); + +if (!css) +continue ; + +cgroup_get (dsct); +prepare_to_wait (&dsct->offline_waitq, &wait, +TASK_UNINTERRUPTIBLE ); + +mutex_unlock (&cgroup_mutex); +schedule (); +finish_wait (&dsct->offline_waitq, &wait); +mutex_lock (&cgroup_mutex); + +cgroup_put (dsct); +return true; + } + } + +return false; +} +/* change the enabled child controllers for a cgroup in the default hierarchy */ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, char *buf, size_t nbytes,
@@ -3048,6 +3095,11 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, goto out_unlock; } +if (cgroup_drain_offline (cgrp)) { +cgroup_kn_unlock (of->kn); +return restart_syscall (); + } +/* * Update subsys masks and calculate what needs to be done. More * subsystems than specified may need to be enabled or disabled
@@ -3063,31 +3115,6 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, enable |= css_enable; disable |= css_disable; -/* -* Because css offlining is asynchronous, userland might try to -* re-enable the same controller while the previous instance is -* still around. In such cases, wait till it's gone using -* offline_waitq. -*/ - do_each_subsys_mask(ss, ssid, css_enable) { -cgroup_for_each_live_child (child, cgrp) { -DEFINE_WAIT (wait); - -if (!cgroup_css (child, ss)) -continue ; - -cgroup_get (child); -prepare_to_wait (&child->offline_waitq, &wait, -TASK_UNINTERRUPTIBLE ); -cgroup_kn_unlock (of->kn); -schedule (); -finish_wait (&child->offline_waitq, &wait); -cgroup_put (child); - -return restart_syscall (); - } - }while_each_subsys_mask (); - cgrp->subtree_control = new_sc; cgrp->subtree_ss_mask = new_ss;
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 7/12 cgroup: factor out cgroup_apply_control_disable() from cgroup_subtree_control_write()
In reply to Tejun HeoFactor out css disabling and hiding into cgroup_apply_control_disable().
* Nest subsystem walk inside child walk. The child walk will later be converted to subtree walk which is a bit more expensive.
* Instead of operating on the differential masks @css_enable and @css_disable, simply disable or hide csses according to the current cgroup_control() and cgroup_ss_mask(). This leads to the same result and is simpler and more robust.
* This allows error handling path to share the same code.
--- kernel/cgroup.c | 74 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 33 deletions(-)
kernel/cgroup.c +41 -33
@@ -3007,6 +3007,43 @@ static bool cgroup_drain_offline(struct cgroup *cgrp)return false; } +/** +* cgroup_apply_control_disable - kill or hide csses according to control +* @cgrp: parent of the target cgroups +* +* Walk @cgrp's children and kill and hide csses so that they match +* cgroup_ss_mask() and cgroup_visible_mask(). +* +* A css is hidden when the userland requests it to be disabled while other +* subsystems are still depending on it. The css must not actively control +* resources and be in the vanilla state if it's made visible again later. +* Controllers which may be depended upon should provide ->css_reset() for +* this purpose. +*/ +static void cgroup_apply_control_disable (struct cgroup *cgrp) +{ +struct cgroup *dsct; +struct cgroup_subsys *ss; +int ssid; + +cgroup_for_each_live_child (dsct, cgrp) { +for_each_subsys (ss, ssid) { +struct cgroup_subsys_state *css =cgroup_css (dsct, ss); + +if (!css) +continue ; + +if (!(cgroup_ss_mask (dsct) & (1 << ss->id))) { +kill_css (css); + }else if (!(cgroup_control (dsct) & (1 << ss->id))) { +css_clear_dir (css,NULL ); +if (ss->css_reset) + ss->css_reset (css); + } + } + } +} +/* change the enabled child controllers for a cgroup in the default hierarchy */ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, char *buf, size_t nbytes,
@@ -3158,27 +3195,8 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,if (ret) goto err_undo_css; -/* -* All tasks are migrated out of disabled csses. Kill or hide -* them. A css is hidden when the userland requests it to be -* disabled while other subsystems are still depending on it. The -* css must not actively control resources and be in the vanilla -* state if it's made visible again later. Controllers which may -* be depended upon should provide ->css_reset() for this purpose. -*/ - do_each_subsys_mask(ss, ssid, disable) { -cgroup_for_each_live_child (child, cgrp) { -struct cgroup_subsys_state *css =cgroup_css (child, ss); - -if (css_disable & (1 << ssid)) { -kill_css (css); - }else { -css_clear_dir (css,NULL ); -if (ss->css_reset) - ss->css_reset (css); - } - } - }while_each_subsys_mask (); +/* all tasks are migrated out of disabled csses, commit disable */ +cgroup_apply_control_disable (cgrp);kernfs_activate (cgrp->kn); ret =0 ;
@@ -3187,22 +3205,12 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,return ret ?: nbytes; err_undo_css: +/* restore masks and shoot down new csses */ cgrp->subtree_control = old_sc; cgrp->subtree_ss_mask = old_ss; - do_each_subsys_mask(ss, ssid, enable) { -cgroup_for_each_live_child (child, cgrp) { -struct cgroup_subsys_state *css =cgroup_css (child, ss); - -if (!css) -continue ; +cgroup_apply_control_disable (cgrp); -if (css_enable & (1 << ssid)) -kill_css (css); -else -css_clear_dir (css,NULL ); - } - }while_each_subsys_mask (); goto out_unlock; }
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 8/12 cgroup: factor out cgroup_apply_control_enable() from cgroup_subtree_control_write()
In reply to Tejun HeoFactor out css enabling and showing into cgroup_apply_control_enable().
* Nest subsystem walk inside child walk. The child walk will later be converted to subtree walk which is a bit more expensive.
* Instead of operating on the differential masks @css_enable, simply enable or show csses according to the current cgroup_control() and cgroup_ss_mask(). This leads to the same result and is simpler and more robust.
--- kernel/cgroup.c | 77 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 30 deletions(-)
kernel/cgroup.c +47 -30
@@ -3008,6 +3008,49 @@ static bool cgroup_drain_offline(struct cgroup *cgrp) }/** +* cgroup_apply_control_enable - enable or show csses according to control +* @cgrp: parent of the target cgroups +* +* Walk @cgrp's children and create new csses or make the existing ones +* visible. A css is created invisible if it's being implicitly enabled +* through dependency. An invisible css is made visible when the userland +* explicitly enables it. +* +* Returns 0 on success, -errno on failure. On failure, csses which have +* been processed already aren't cleaned up. The caller is responsible for +* cleaning up with cgroup_apply_control_disble(). +*/ +static int cgroup_apply_control_enable (struct cgroup *cgrp) +{ +struct cgroup *dsct; +struct cgroup_subsys *ss; +int ssid, ret; + +cgroup_for_each_live_child (dsct, cgrp) { +for_each_subsys (ss, ssid) { +struct cgroup_subsys_state *css =cgroup_css (dsct, ss); + +if (!(cgroup_ss_mask (dsct) & (1 << ss->id))) +continue ; + +if (!css) { + css =css_create (dsct, ss); +if (IS_ERR (css)) +return PTR_ERR (css); + } + +if (cgroup_control (dsct) & (1 << ss->id)) { + ret =css_populate_dir (css,NULL ); +if (ret) +return ret; + } + } + } + +return 0 ; +} + +/** * cgroup_apply_control_disable - kill or hide csses according to control * @cgrp: parent of the target cgroups *
@@ -3155,36 +3198,10 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, cgrp->subtree_control = new_sc; cgrp->subtree_ss_mask = new_ss; -/* -* Create new csses or make the existing ones visible. A css is -* created invisible if it's being implicitly enabled through -* dependency. An invisible css is made visible when the userland -* explicitly enables it. -*/ - do_each_subsys_mask(ss, ssid, enable) { -cgroup_for_each_live_child (child, cgrp) { -if (css_enable & (1 << ssid)) { -struct cgroup_subsys_state *css; - - css =css_create (child, ss); -if (IS_ERR (css)) { - ret =PTR_ERR (css); - goto err_undo_css; - } - -if (cgrp->subtree_control & (1 << ssid)) { - ret =css_populate_dir (css,NULL ); -if (ret) - goto err_undo_css; - } - }else { - ret =css_populate_dir (cgroup_css (child, ss), -NULL ); -if (ret) - goto err_undo_css; - } - } - }while_each_subsys_mask (); +/* prepare csses */ + ret =cgroup_apply_control_enable (cgrp); +if (ret) + goto err_undo_css;/* * At this point, cgroup_e_css() results reflect the new csses
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 9/12 cgroup: make cgroup_drain_offline() and cgroup_apply_control_{disable|enable}() recursive
In reply to Tejun HeoThe three factored out css management operations - cgroup_drain_offline() and cgroup_apply_control_{disable|enable}() - only depend on the current state of the target cgroups and idempotent and thus can be easily made to operate on the subtree instead of the immediate children.
This patch introduces the iterators which walk live subtree and converts the three functions to operate on the subtree including self instead of the children. While this leads to spurious walking and be slightly more expensive, it will allow them to be used for wider scope of operations.
Note that cgroup_drain_offline() now tests for whether a css is dying before trying to drain it. This is to avoid trying to drain live csses as there can be mix of live and dying csses in a subtree unlike children of the same parent.
--- kernel/cgroup.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-)
kernel/cgroup.c +31 -10
@@ -569,6 +569,24 @@ static int notify_on_release(const struct cgroup *cgrp) ; \ else +/* walk live descendants in preorder */ +#define cgroup_for_each_live_descendant_pre (dsct, d_css, cgrp) \ + css_for_each_descendant_pre((d_css), cgroup_css((cgrp), NULL)) \ + if (({ lockdep_assert_held(&cgroup_mutex); \ + (dsct) = (d_css)->cgroup; \ + cgroup_is_dead(dsct); })) \ + ; \ + else + +/* walk live descendants in postorder */ +#define cgroup_for_each_live_descendant_post (dsct, d_css, cgrp) \ + css_for_each_descendant_post((d_css), cgroup_css((cgrp), NULL)) \ + if (({ lockdep_assert_held(&cgroup_mutex); \ + (dsct) = (d_css)->cgroup; \ + cgroup_is_dead(dsct); })) \ + ; \ + else +static void cgroup_release_agent (struct work_struct *work);static void check_for_release (struct cgroup *cgrp);
@@ -2962,11 +2980,11 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)/** * cgroup_drain_offline - wait for previously offlined csses to go away -* @cgrp: parent of the target cgroups +* @cgrp: root of the target subtree * * Because css offlining is asynchronous, userland may try to re-enable a * controller while the previous css is still around. This function drains -* the previous css instances of @cgrp's children. +* the previous css instances of @cgrp's subtree. * * Must be called with cgroup_mutex held. Returns %false if there were no * dying css instances. Returns %true if there were one or more and this
@@ -2977,17 +2995,18 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)static bool cgroup_drain_offline (struct cgroup *cgrp) {struct cgroup *dsct; +struct cgroup_subsys_state *d_css;struct cgroup_subsys *ss;int ssid;lockdep_assert_held (&cgroup_mutex); -cgroup_for_each_live_child (dsct, cgrp) { +cgroup_for_each_live_descendant_post (dsct, d_css, cgrp) {for_each_subsys (ss, ssid) {struct cgroup_subsys_state *css =cgroup_css (dsct, ss);DEFINE_WAIT (wait); -if (!css) +if (!css || !percpu_ref_is_dying (&css->refcnt))continue ;cgroup_get (dsct);
@@ -3009,9 +3028,9 @@ static bool cgroup_drain_offline(struct cgroup *cgrp)/** * cgroup_apply_control_enable - enable or show csses according to control -* @cgrp: parent of the target cgroups +* @cgrp: root of the target subtree * -* Walk @cgrp's children and create new csses or make the existing ones +* Walk @cgrp's subtree and create new csses or make the existing ones * visible. A css is created invisible if it's being implicitly enabled * through dependency. An invisible css is made visible when the userland * explicitly enables it.
@@ -3023,10 +3042,11 @@ static bool cgroup_drain_offline(struct cgroup *cgrp)static int cgroup_apply_control_enable (struct cgroup *cgrp) {struct cgroup *dsct; +struct cgroup_subsys_state *d_css;struct cgroup_subsys *ss;int ssid, ret; -cgroup_for_each_live_child (dsct, cgrp) { +cgroup_for_each_live_descendant_pre (dsct, d_css, cgrp) {for_each_subsys (ss, ssid) {struct cgroup_subsys_state *css =cgroup_css (dsct, ss);
@@ -3052,9 +3072,9 @@ static int cgroup_apply_control_enable(struct cgroup *cgrp)/** * cgroup_apply_control_disable - kill or hide csses according to control -* @cgrp: parent of the target cgroups +* @cgrp: root of the target subtree * -* Walk @cgrp's children and kill and hide csses so that they match +* Walk @cgrp's subtree and kill and hide csses so that they match * cgroup_ss_mask() and cgroup_visible_mask(). * * A css is hidden when the userland requests it to be disabled while other
@@ -3066,10 +3086,11 @@ static int cgroup_apply_control_enable(struct cgroup *cgrp)static void cgroup_apply_control_disable (struct cgroup *cgrp) {struct cgroup *dsct; +struct cgroup_subsys_state *d_css;struct cgroup_subsys *ss;int ssid; -cgroup_for_each_live_child (dsct, cgrp) { +cgroup_for_each_live_descendant_post (dsct, d_css, cgrp) {for_each_subsys (ss, ssid) {struct cgroup_subsys_state *css =cgroup_css (dsct, ss);
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 10/12 cgroup: introduce cgroup_{save|propagate|restore}_control()
In reply to Tejun HeoWhile controllers are being enabled and disabled in cgroup_subtree_control_write(), the original subsystem masks are stashed in local variables so that they can be restored if the operation fails in the middle.
This patch adds dedicated fields to struct cgroup to be used instead of the local variables and implements functions to stash the current values, propagate the changes and restore them recursively. Combined with the previous changes, this makes subsystem management operations fully recursive and modularlized. This will be used to expand cgroup core functionalities.
While at it, remove now unused @css_enable and @css_disable from cgroup_subtree_control_write().
--- include/linux/cgroup-defs.h | 2 ++ kernel/cgroup.c | 82 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 20 deletions(-)
include/linux/cgroup-defs.h +2 -0
@@ -260,6 +260,8 @@ struct cgroup {*/ u16 subtree_control;u16 subtree_ss_mask; +u16 old_subtree_control; +u16 old_subtree_ss_mask;/* Private pointers for each registered subsystem */ struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT ];
kernel/cgroup.c +62 -20
109 lines not on this page · raw message
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 11/12 cgroup: Factor out cgroup_{apply|finalize}_control() from cgroup_subtree_control_write()
In reply to Tejun HeoFactor out cgroup_{apply|finalize}_control() so that control mask update can be done in several simple steps. This patch doesn't introduce behavior changes.
--- kernel/cgroup.c | 81 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 23 deletions(-)
kernel/cgroup.c +58 -23
@@ -3164,6 +3164,62 @@ static void cgroup_apply_control_disable(struct cgroup *cgrp) } } +/** +* cgroup_apply_control - apply control mask updates to the subtree +* @cgrp: root of the target subtree +* +* subsystems can be enabled and disabled in a subtree using the following +* steps. +* +* 1. Call cgroup_save_control() to stash the current state. +* 2. Update ->subtree_control masks in the subtree as desired. +* 3. Call cgroup_apply_control() to apply the changes. +* 4. Optionally perform other related operations. +* 5. Call cgroup_finalize_control() to finish up. +* +* This function implements step 3 and propagates the mask changes +* throughout @cgrp's subtree, updates csses accordingly and perform +* process migrations. +*/ +static int cgroup_apply_control (struct cgroup *cgrp) +{ +int ret; + +cgroup_propagate_control (cgrp); + + ret =cgroup_apply_control_enable (cgrp); +if (ret) +return ret; + +/* +* At this point, cgroup_e_css() results reflect the new csses +* making the following cgroup_update_dfl_csses() properly update +* css associations of all tasks in the subtree. +*/ + ret =cgroup_update_dfl_csses (cgrp); +if (ret) +return ret; + +return 0 ; +} + +/** +* cgroup_finalize_control - finalize control mask update +* @cgrp: root of the target subtree +* @ret: the result of the update +* +* Finalize control mask update. See cgroup_apply_control() for more info. +*/ +static void cgroup_finalize_control (struct cgroup *cgrp,int ret) +{ +if (ret) { +cgroup_restore_control (cgrp); +cgroup_propagate_control (cgrp); + } + +cgroup_apply_control_disable (cgrp); +} +/* change the enabled child controllers for a cgroup in the default hierarchy */ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, char *buf, size_t nbytes,
@@ -3262,36 +3318,15 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, cgrp->subtree_control |= enable; cgrp->subtree_control &= ~disable; -cgroup_propagate_control (cgrp); + ret =cgroup_apply_control (cgrp); - ret =cgroup_apply_control_enable (cgrp); -if (ret) - goto err_undo_css; - -/* -* At this point, cgroup_e_css() results reflect the new csses -* making the following cgroup_update_dfl_csses() properly update -* css associations of all tasks in the subtree. -*/ - ret =cgroup_update_dfl_csses (cgrp); -if (ret) - goto err_undo_css; - -/* all tasks are migrated out of disabled csses, commit disable */ -cgroup_apply_control_disable (cgrp); +cgroup_finalize_control (cgrp, ret);kernfs_activate (cgrp->kn); ret =0 ; out_unlock:cgroup_kn_unlock (of->kn);return ret ?: nbytes; - -err_undo_css: -/* restore masks and shoot down new csses */ -cgroup_restore_control (cgrp); -cgroup_apply_control_disable (cgrp); - - goto out_unlock; }static int cgroup_events_show (struct seq_file *seq,void *v)
Signature · 1 line
2.5.0
Tejun Heo
maintainerPATCH 12/12 cgroup: make cgroup_calc_subtree_ss_mask() take @this_ss_mask
In reply to Tejun Heocgroup_calc_subtree_ss_mask() currently takes @cgrp and @subtree_control. @cgrp is used for two purposes - to decide whether it's for default hierarchy and the mask of available subsystems. The former doesn't matter as the results are the same regardless. The latter can be specified directly through a subsystem mask.
This patch makes cgroup_calc_subtree_ss_mask() perform the same calculations for both default and legacy hierarchies and take @this_ss_mask for available subsystems. @cgrp is no longer used and dropped. This is to allow using the function in contexts where available controllers can't be decided from the cgroup.
This patch also drops cgroup_refresh_subtree_ss_mask(). It's a thin wrapper which saves a bit of typing but the saving is pretty small and planned changes will make its uses look inconsistent compared to usages which don't update cgroups.
--- kernel/cgroup.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-)
kernel/cgroup.c +16 -26
@@ -1301,18 +1301,17 @@ static umode_t cgroup_file_mode(const struct cftype *cft)/** * cgroup_calc_subtree_ss_mask - calculate subtree_ss_mask -* @cgrp: the target cgroup * @subtree_control: the new subtree_control mask to consider +* @this_ss_mask: available subsystems * * On the default hierarchy, a subsystem may request other subsystems to be * enabled together through its ->depends_on mask. In such cases, more * subsystems than specified in "cgroup.subtree_control" may be enabled. * * This function calculates which subsystems need to be enabled if -* @subtree_control is to be applied to @cgrp. The returned mask is always -* a superset of @subtree_control and follows the usual hierarchy rules. +* @subtree_control is to be applied while restricted to @this_ss_mask. */ -static u16 cgroup_calc_subtree_ss_mask (struct cgroup *cgrp,u16 subtree_control) +static u16 cgroup_calc_subtree_ss_mask (u16 subtree_control,u16 this_ss_mask) {u16 cur_ss_mask = subtree_control;struct cgroup_subsys *ss;
@@ -1320,9 +1319,6 @@ static u16 cgroup_calc_subtree_ss_mask(struct cgroup *cgrp, u16 subtree_control)lockdep_assert_held (&cgroup_mutex); -if (!cgroup_on_dfl (cgrp)) -return cur_ss_mask; -while (true) {u16 new_ss_mask = cur_ss_mask;
@@ -1335,7 +1331,7 @@ static u16 cgroup_calc_subtree_ss_mask(struct cgroup *cgrp, u16 subtree_control)* happen only if some depended-upon subsystems were bound * to non-default hierarchies. */ - new_ss_mask &=cgroup_ss_mask (cgrp); + new_ss_mask &= this_ss_mask;if (new_ss_mask == cur_ss_mask)break ;
@@ -1346,19 +1342,6 @@ static u16 cgroup_calc_subtree_ss_mask(struct cgroup *cgrp, u16 subtree_control) }/** -* cgroup_refresh_subtree_ss_mask - update subtree_ss_mask -* @cgrp: the target cgroup -* -* Update @cgrp->subtree_ss_mask according to the current -* @cgrp->subtree_control using cgroup_calc_subtree_ss_mask(). -*/ -static void cgroup_refresh_subtree_ss_mask (struct cgroup *cgrp) -{ - cgrp->subtree_ss_mask = -cgroup_calc_subtree_ss_mask (cgrp, cgrp->subtree_control); -} - -/** * cgroup_kn_unlock - unlocking helper for cgroup kernfs methods * @kn: the kernfs_node being serviced *
@@ -1592,7 +1575,9 @@ static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) src_root->subsys_mask &= ~(1 << ssid); scgrp->subtree_control &= ~(1 << ssid); -cgroup_refresh_subtree_ss_mask (scgrp); + scgrp->subtree_ss_mask = +cgroup_calc_subtree_ss_mask (scgrp->subtree_control, +cgroup_ss_mask (scgrp));/* default hierarchy doesn't enable controllers by default */ dst_root->subsys_mask |=1 << ssid;
@@ -1600,7 +1585,9 @@ static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)static_branch_enable (cgroup_subsys_on_dfl_key[ssid]); }else { dcgrp->subtree_control |=1 << ssid; -cgroup_refresh_subtree_ss_mask (dcgrp); + dcgrp->subtree_ss_mask = +cgroup_calc_subtree_ss_mask (dcgrp->subtree_control, +cgroup_ss_mask (dcgrp));static_branch_disable (cgroup_subsys_on_dfl_key[ssid]); }
@@ -3059,8 +3046,9 @@ static void cgroup_propagate_control(struct cgroup *cgrp)cgroup_for_each_live_descendant_pre (dsct, d_css, cgrp) { dsct->subtree_control &=cgroup_control (dsct); - dsct->subtree_ss_mask =cgroup_calc_subtree_ss_mask (dsct, - dsct->subtree_control); + dsct->subtree_ss_mask = +cgroup_calc_subtree_ss_mask (dsct->subtree_control, +cgroup_ss_mask (dsct)); } }
@@ -5108,7 +5096,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent)*/ if (!cgroup_on_dfl (cgrp)) { cgrp->subtree_control =cgroup_control (cgrp); -cgroup_refresh_subtree_ss_mask (cgrp); + cgrp->subtree_ss_mask = +cgroup_calc_subtree_ss_mask (cgrp->subtree_control, +cgroup_ss_mask (cgrp)); }return cgrp;
Signature · 1 line
2.5.0