mirror of
https://github.com/torvalds/linux.git
synced 2026-11-09 13:44:03 +01:00
cgroup: Track the effective css in each cgroup
cgroup_e_css() and cgroup_get_e_css() find the effective css by walking up the hierarchy until they reach a cgroup that has the subsystem enabled. Per-I/O users such as nvmet need this lookup to be O(1). Track the effective css in each cgroup and make cgroup_e_css() and cgroup_get_e_css() use it. When a css is brought online or offline, update the effective css of its cgroup and of all descendants. Signed-off-by: Peng Yu <yupeng0921@gmail.com> Assisted-by: Claude:claude-fable-5 [Claude Code] Assisted-by: Claude:claude-opus-5-5 [Claude Code] Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
5a711e2fc9
commit
d5632ae015
|
|
@ -555,6 +555,14 @@ struct cgroup {
|
|||
/* Private pointers for each registered subsystem */
|
||||
struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT];
|
||||
|
||||
/*
|
||||
* Effective css for each subsystem: the css of the nearest ancestor,
|
||||
* including this cgroup, that has the subsystem enabled, or the root
|
||||
* css if the subsystem isn't bound to this hierarchy. Updated under
|
||||
* cgroup_mutex and read under RCU.
|
||||
*/
|
||||
struct cgroup_subsys_state __rcu *e_css[CGROUP_SUBSYS_COUNT];
|
||||
|
||||
/*
|
||||
* Keep track of total number of dying CSSes at and below this cgroup.
|
||||
* Protected by cgroup_mutex.
|
||||
|
|
|
|||
|
|
@ -548,20 +548,11 @@ static struct cgroup_subsys_state *cgroup_e_css_by_mask(struct cgroup *cgrp,
|
|||
struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp,
|
||||
struct cgroup_subsys *ss)
|
||||
{
|
||||
struct cgroup_subsys_state *css;
|
||||
|
||||
if (!CGROUP_HAS_SUBSYS_CONFIG)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
css = cgroup_css(cgrp, ss);
|
||||
|
||||
if (css)
|
||||
return css;
|
||||
cgrp = cgroup_parent(cgrp);
|
||||
} while (cgrp);
|
||||
|
||||
return init_css_set.subsys[ss->id];
|
||||
return rcu_dereference_check(cgrp->e_css[ss->id],
|
||||
lockdep_is_held(&cgroup_mutex));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -585,17 +576,10 @@ struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgrp,
|
|||
|
||||
rcu_read_lock();
|
||||
|
||||
do {
|
||||
css = cgroup_css(cgrp, ss);
|
||||
css = cgroup_e_css(cgrp, ss);
|
||||
while (!css_tryget_online(css))
|
||||
css = cgroup_e_css(cgroup_parent(css->cgroup), ss);
|
||||
|
||||
if (css && css_tryget_online(css))
|
||||
goto out_unlock;
|
||||
cgrp = cgroup_parent(cgrp);
|
||||
} while (cgrp);
|
||||
|
||||
css = init_css_set.subsys[ss->id];
|
||||
css_get(css);
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
return css;
|
||||
}
|
||||
|
|
@ -2142,12 +2126,24 @@ void init_cgroup_root(struct cgroup_fs_context *ctx)
|
|||
{
|
||||
struct cgroup_root *root = ctx->root;
|
||||
struct cgroup *cgrp = &root->cgrp;
|
||||
struct cgroup_subsys *ss;
|
||||
int ssid;
|
||||
|
||||
INIT_LIST_HEAD_RCU(&root->root_list);
|
||||
atomic_set(&root->nr_cgrps, 1);
|
||||
cgrp->root = root;
|
||||
init_cgroup_housekeeping(cgrp);
|
||||
|
||||
/*
|
||||
* A root cgroup's effective css is always the root css in
|
||||
* init_css_set.subsys[], whichever hierarchy the subsystem is bound
|
||||
* to, so rebind_subsystems() doesn't need to update e_css[]. For
|
||||
* cgrp_dfl_root this runs before the root csses exist, and
|
||||
* online_css() sets the entries when they come online.
|
||||
*/
|
||||
for_each_subsys(ss, ssid)
|
||||
RCU_INIT_POINTER(cgrp->e_css[ssid], init_css_set.subsys[ssid]);
|
||||
|
||||
/* DYNMODS must be modified through cgroup_favor_dynmods() */
|
||||
root->flags = ctx->flags & ~CGRP_ROOT_FAVOR_DYNMODS;
|
||||
if (ctx->release_agent)
|
||||
|
|
@ -5874,6 +5870,22 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
|
|||
BUG_ON(cgroup_css(cgrp, ss));
|
||||
}
|
||||
|
||||
static void cgroup_update_e_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
|
||||
{
|
||||
struct cgroup_subsys_state *d_css;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
||||
css_for_each_descendant_pre(d_css, &cgrp->self) {
|
||||
struct cgroup *dsct = d_css->cgroup;
|
||||
struct cgroup_subsys_state *css = cgroup_css(dsct, ss);
|
||||
|
||||
if (!css)
|
||||
css = cgroup_e_css(cgroup_parent(dsct), ss);
|
||||
rcu_assign_pointer(dsct->e_css[ss->id], css);
|
||||
}
|
||||
}
|
||||
|
||||
/* invoke ->css_online() on a new CSS and mark it online if successful */
|
||||
static int online_css(struct cgroup_subsys_state *css)
|
||||
{
|
||||
|
|
@ -5887,6 +5899,7 @@ static int online_css(struct cgroup_subsys_state *css)
|
|||
if (!ret) {
|
||||
css->flags |= CSS_ONLINE;
|
||||
rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
|
||||
cgroup_update_e_css(css->cgroup, ss);
|
||||
|
||||
atomic_inc(&css->online_cnt);
|
||||
if (css->parent) {
|
||||
|
|
@ -5913,6 +5926,7 @@ static void offline_css(struct cgroup_subsys_state *css)
|
|||
|
||||
css->flags &= ~CSS_ONLINE;
|
||||
RCU_INIT_POINTER(css->cgroup->subsys[ss->id], NULL);
|
||||
cgroup_update_e_css(css->cgroup, ss);
|
||||
|
||||
wake_up_all(&css->cgroup->offline_waitq);
|
||||
}
|
||||
|
|
@ -5984,6 +5998,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
|
|||
{
|
||||
struct cgroup_root *root = parent->root;
|
||||
struct cgroup *cgrp, *tcgrp;
|
||||
struct cgroup_subsys *ss;
|
||||
struct kernfs_node *kn;
|
||||
int i, level = parent->level + 1;
|
||||
int ret;
|
||||
|
|
@ -6028,6 +6043,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
|
|||
for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp))
|
||||
cgrp->ancestors[tcgrp->level] = tcgrp;
|
||||
|
||||
for_each_subsys(ss, i)
|
||||
RCU_INIT_POINTER(cgrp->e_css[i], cgroup_e_css(parent, ss));
|
||||
|
||||
/*
|
||||
* New cgroup inherits effective freeze counter, and
|
||||
* if the parent has to be frozen, the child has too.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user