|
@@ -178,7 +178,6 @@ static struct cftype cgroup_base_files[];
|
|
static void cgroup_put(struct cgroup *cgrp);
|
|
static void cgroup_put(struct cgroup *cgrp);
|
|
static int rebind_subsystems(struct cgroup_root *dst_root,
|
|
static int rebind_subsystems(struct cgroup_root *dst_root,
|
|
unsigned int ss_mask);
|
|
unsigned int ss_mask);
|
|
-static void cgroup_destroy_css_killed(struct cgroup *cgrp);
|
|
|
|
static int cgroup_destroy_locked(struct cgroup *cgrp);
|
|
static int cgroup_destroy_locked(struct cgroup *cgrp);
|
|
static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss);
|
|
static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss);
|
|
static void kill_css(struct cgroup_subsys_state *css);
|
|
static void kill_css(struct cgroup_subsys_state *css);
|
|
@@ -4169,7 +4168,6 @@ static int online_css(struct cgroup_subsys_state *css)
|
|
ret = ss->css_online(css);
|
|
ret = ss->css_online(css);
|
|
if (!ret) {
|
|
if (!ret) {
|
|
css->flags |= CSS_ONLINE;
|
|
css->flags |= CSS_ONLINE;
|
|
- css->cgroup->nr_css++;
|
|
|
|
rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
|
|
rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
|
|
}
|
|
}
|
|
return ret;
|
|
return ret;
|
|
@@ -4189,7 +4187,6 @@ static void offline_css(struct cgroup_subsys_state *css)
|
|
ss->css_offline(css);
|
|
ss->css_offline(css);
|
|
|
|
|
|
css->flags &= ~CSS_ONLINE;
|
|
css->flags &= ~CSS_ONLINE;
|
|
- css->cgroup->nr_css--;
|
|
|
|
RCU_INIT_POINTER(css->cgroup->subsys[ss->id], NULL);
|
|
RCU_INIT_POINTER(css->cgroup->subsys[ss->id], NULL);
|
|
|
|
|
|
wake_up_all(&css->cgroup->offline_waitq);
|
|
wake_up_all(&css->cgroup->offline_waitq);
|
|
@@ -4374,39 +4371,18 @@ out_destroy:
|
|
|
|
|
|
/*
|
|
/*
|
|
* This is called when the refcnt of a css is confirmed to be killed.
|
|
* This is called when the refcnt of a css is confirmed to be killed.
|
|
- * css_tryget_online() is now guaranteed to fail.
|
|
|
|
|
|
+ * css_tryget_online() is now guaranteed to fail. Tell the subsystem to
|
|
|
|
+ * initate destruction and put the css ref from kill_css().
|
|
*/
|
|
*/
|
|
static void css_killed_work_fn(struct work_struct *work)
|
|
static void css_killed_work_fn(struct work_struct *work)
|
|
{
|
|
{
|
|
struct cgroup_subsys_state *css =
|
|
struct cgroup_subsys_state *css =
|
|
container_of(work, struct cgroup_subsys_state, destroy_work);
|
|
container_of(work, struct cgroup_subsys_state, destroy_work);
|
|
- struct cgroup *cgrp = css->cgroup;
|
|
|
|
|
|
|
|
mutex_lock(&cgroup_mutex);
|
|
mutex_lock(&cgroup_mutex);
|
|
-
|
|
|
|
- /*
|
|
|
|
- * css_tryget_online() is guaranteed to fail now. Tell subsystems
|
|
|
|
- * to initate destruction.
|
|
|
|
- */
|
|
|
|
offline_css(css);
|
|
offline_css(css);
|
|
-
|
|
|
|
- /*
|
|
|
|
- * If @cgrp is marked dead, it's waiting for refs of all css's to
|
|
|
|
- * be disabled before proceeding to the second phase of cgroup
|
|
|
|
- * destruction. If we are the last one, kick it off.
|
|
|
|
- */
|
|
|
|
- if (!cgrp->nr_css && cgroup_is_dead(cgrp))
|
|
|
|
- cgroup_destroy_css_killed(cgrp);
|
|
|
|
-
|
|
|
|
mutex_unlock(&cgroup_mutex);
|
|
mutex_unlock(&cgroup_mutex);
|
|
|
|
|
|
- /*
|
|
|
|
- * Put the css refs from kill_css(). Each css holds an extra
|
|
|
|
- * reference to the cgroup's dentry and cgroup removal proceeds
|
|
|
|
- * regardless of css refs. On the last put of each css, whenever
|
|
|
|
- * that may be, the extra dentry ref is put so that dentry
|
|
|
|
- * destruction happens only after all css's are released.
|
|
|
|
- */
|
|
|
|
css_put(css);
|
|
css_put(css);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4518,11 +4494,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|
*/
|
|
*/
|
|
set_bit(CGRP_DEAD, &cgrp->flags);
|
|
set_bit(CGRP_DEAD, &cgrp->flags);
|
|
|
|
|
|
- /*
|
|
|
|
- * Initiate massacre of all css's. cgroup_destroy_css_killed()
|
|
|
|
- * will be invoked to perform the rest of destruction once the
|
|
|
|
- * percpu refs of all css's are confirmed to be killed.
|
|
|
|
- */
|
|
|
|
|
|
+ /* initiate massacre of all css's */
|
|
for_each_css(css, ssid, cgrp)
|
|
for_each_css(css, ssid, cgrp)
|
|
kill_css(css);
|
|
kill_css(css);
|
|
|
|
|
|
@@ -4532,15 +4504,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|
list_del_init(&cgrp->release_list);
|
|
list_del_init(&cgrp->release_list);
|
|
raw_spin_unlock(&release_list_lock);
|
|
raw_spin_unlock(&release_list_lock);
|
|
|
|
|
|
- /*
|
|
|
|
- * If @cgrp has css's attached, the second stage of cgroup
|
|
|
|
- * destruction is kicked off from css_killed_work_fn() after the
|
|
|
|
- * refs of all attached css's are killed. If @cgrp doesn't have
|
|
|
|
- * any css, we kick it off here.
|
|
|
|
- */
|
|
|
|
- if (!cgrp->nr_css)
|
|
|
|
- cgroup_destroy_css_killed(cgrp);
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Remove @cgrp directory along with the base files. @cgrp has an
|
|
* Remove @cgrp directory along with the base files. @cgrp has an
|
|
* extra ref on its kn.
|
|
* extra ref on its kn.
|
|
@@ -4550,25 +4513,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|
set_bit(CGRP_RELEASABLE, &cgrp->parent->flags);
|
|
set_bit(CGRP_RELEASABLE, &cgrp->parent->flags);
|
|
check_for_release(cgrp->parent);
|
|
check_for_release(cgrp->parent);
|
|
|
|
|
|
|
|
+ /* put the base reference */
|
|
|
|
+ cgroup_put(cgrp);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
};
|
|
};
|
|
|
|
|
|
-/**
|
|
|
|
- * cgroup_destroy_css_killed - the second step of cgroup destruction
|
|
|
|
- * @cgrp: the cgroup whose csses have just finished offlining
|
|
|
|
- *
|
|
|
|
- * This function is invoked from a work item for a cgroup which is being
|
|
|
|
- * destroyed after all css's are offlined and performs the rest of
|
|
|
|
- * destruction. This is the second step of destruction described in the
|
|
|
|
- * comment above cgroup_destroy_locked().
|
|
|
|
- */
|
|
|
|
-static void cgroup_destroy_css_killed(struct cgroup *cgrp)
|
|
|
|
-{
|
|
|
|
- lockdep_assert_held(&cgroup_mutex);
|
|
|
|
-
|
|
|
|
- cgroup_put(cgrp);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int cgroup_rmdir(struct kernfs_node *kn)
|
|
static int cgroup_rmdir(struct kernfs_node *kn)
|
|
{
|
|
{
|
|
struct cgroup *cgrp;
|
|
struct cgroup *cgrp;
|