diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 618838c48313cd..b886d3d41bdf53 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -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)) { +printk("!!! css_put is ALREADY zero css %llx !!!\n", css); + } + + if (!(css->flags & CSS_NO_REF)) { 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; + } + } } /** @@ -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) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 0853289d321a53..05f3efa272be81 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -2162,6 +2162,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(). @@ -5108,6 +5109,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); } @@ -5197,6 +5199,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); @@ -5477,6 +5480,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); } @@ -5556,6 +5560,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); @@ -5573,7 +5578,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 @@ -5588,8 +5592,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); @@ -5616,6 +5627,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;