Skip to content

Commit

Permalink
cgroup: test css_put imbalance
Browse files Browse the repository at this point in the history
Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
Change-Id: I0d3d27cdff508b2bb9ae2411d406f272ca46d410
  • Loading branch information
tstruk committed May 31, 2022
1 parent 56c31ac commit 04a2b74
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
25 changes: 23 additions & 2 deletions include/linux/cgroup.h
Expand Up @@ -400,8 +400,19 @@ static inline bool css_is_dying(struct cgroup_subsys_state *css)
*/
static inline void css_put(struct cgroup_subsys_state *css)
{
if (!(css->flags & CSS_NO_REF))
if (percpu_ref_is_zero(&css->refcnt) || percpu_ref_is_dying(&css->refcnt)) {
printk("!!! css_put is ALREADY zero css or dying %llx !!!\n", css);
return;
}

if (!(css->flags & CSS_NO_REF || percpu_ref_is_dying(&css->refcnt))) {
percpu_ref_put(&css->refcnt);

if (percpu_ref_is_zero(&css->refcnt)) {
printk("!!! css_put is zero set CSS_NO_REF css %llx !!!\n", css);
css->flags |= CSS_NO_REF;
}
}
}

/**
Expand All @@ -413,8 +424,18 @@ static inline void css_put(struct cgroup_subsys_state *css)
*/
static inline void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
{
if (!(css->flags & CSS_NO_REF))
if (percpu_ref_is_zero(&css->refcnt)) {
printk("!!! css_put_many is ALREADY zero css %llx !!!\n", css);
}

if (!(css->flags & CSS_NO_REF)) {
percpu_ref_put_many(&css->refcnt, n);

if (percpu_ref_is_zero(&css->refcnt)) {
printk("!!! css_put_many is zero set CSS_NO_REF css %llx !!!\n", css);
css->flags |= CSS_NO_REF;
}
}
}

static inline void cgroup_get(struct cgroup *cgrp)
Expand Down
21 changes: 19 additions & 2 deletions kernel/cgroup/cgroup.c
Expand Up @@ -1562,6 +1562,8 @@ void cgroup_kn_unlock(struct kernfs_node *kn)
mutex_unlock(&cgroup_mutex);

kernfs_unbreak_active_protection(kn);
printk("!!!!!!!! cgroup_kn_lock_live: cgrp->self.flags & CSS_NO_REF %d !!\n", cgrp->self.flags & CSS_NO_REF);

cgroup_put(cgrp);
}

Expand Down Expand Up @@ -1597,6 +1599,7 @@ struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn, bool drain_offline)
* protection against removal. Ensure @cgrp stays accessible and
* break the active_ref protection.
*/
printk("!!!!!!!! cgroup_kn_lock_live: css->flags & CSS_NO_REF %d !!\n", cgrp->self.flags & CSS_NO_REF);
if (!cgroup_tryget(cgrp))
return NULL;
kernfs_break_active_protection(kn);
Expand Down Expand Up @@ -2162,6 +2165,7 @@ static void cgroup_kill_sb(struct super_block *sb)
struct kernfs_root *kf_root = kernfs_root_from_sb(sb);
struct cgroup_root *root = cgroup_root_from_kf(kf_root);

printk("!!! cgroup_kill_sb killing css %llx !!!\n", root->cgrp.self);
/*
* If @root doesn't have any children, start killing it.
* This prevents new mounts by disabling percpu_ref_tryget_live().
Expand Down Expand Up @@ -3118,6 +3122,7 @@ static void cgroup_apply_control_disable(struct cgroup *cgrp)
struct cgroup_subsys *ss;
int ssid;

printk("!!! cgroup_apply_control_disable\n");
cgroup_for_each_live_descendant_post(dsct, d_css, cgrp) {
for_each_subsys(ss, ssid) {
struct cgroup_subsys_state *css = cgroup_css(dsct, ss);
Expand All @@ -3129,6 +3134,7 @@ static void cgroup_apply_control_disable(struct cgroup *cgrp)

if (css->parent &&
!(cgroup_ss_mask(dsct) & (1 << ss->id))) {
printk("!!! cgroup_apply_control_disable kill_css %llx\n", css);
kill_css(css);
} else if (!css_visible(css)) {
css_clear_dir(css);
Expand Down Expand Up @@ -5108,6 +5114,7 @@ static void css_release(struct percpu_ref *ref)
struct cgroup_subsys_state *css =
container_of(ref, struct cgroup_subsys_state, refcnt);

printk("!!! css_release css %llx !!!\n", css);
INIT_WORK(&css->destroy_work, css_release_work_fn);
queue_work(cgroup_destroy_wq, &css->destroy_work);
}
Expand Down Expand Up @@ -5197,6 +5204,7 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
struct cgroup_subsys_state *css;
int err;

printk("!!! css_create !!!\n");
lockdep_assert_held(&cgroup_mutex);

css = ss->css_alloc(parent_css);
Expand Down Expand Up @@ -5477,6 +5485,7 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
container_of(ref, struct cgroup_subsys_state, refcnt);

if (atomic_dec_and_test(&css->online_cnt)) {
printk("!!! css_killed_ref_fn css %llx !!!\n", css);
INIT_WORK(&css->destroy_work, css_killed_work_fn);
queue_work(cgroup_destroy_wq, &css->destroy_work);
}
Expand Down Expand Up @@ -5556,6 +5565,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
struct cgroup_subsys_state *css;
struct cgrp_cset_link *link;
int ssid;
printk("!!! cgroup_destroy_locked !!!\n");

lockdep_assert_held(&cgroup_mutex);

Expand All @@ -5573,7 +5583,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
*/
if (css_has_online_children(&cgrp->self))
return -EBUSY;

/*
* Mark @cgrp and the associated csets dead. The former prevents
* further task migration and child creation by disabling
Expand All @@ -5588,8 +5597,15 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
spin_unlock_irq(&css_set_lock);

/* initiate massacre of all css's */
for_each_css(css, ssid, cgrp)
for_each_css(css, ssid, cgrp) {
printk("!!! cgroup_destroy_locked kill all css'es !!!\n");
if (css == &cgrp->self) {
printk("!!! cgroup_destroy_locked skipping css %llx !!!\n", css);
continue;
}

kill_css(css);
}

/* clear and remove @cgrp dir, @cgrp has an extra ref on its kn */
css_clear_dir(&cgrp->self);
Expand All @@ -5616,6 +5632,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
cgroup_bpf_offline(cgrp);

/* put the base reference */
printk("!!! cgroup_destroy_locked killing css %llx !!!\n", &cgrp->self);
percpu_ref_kill(&cgrp->self.refcnt);

return 0;
Expand Down

0 comments on commit 04a2b74

Please sign in to comment.