diff options
-rw-r--r-- | include/linux/cgroup.h | 2 | ||||
-rw-r--r-- | kernel/cgroup.c | 52 |
2 files changed, 25 insertions, 29 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 80dca872f4d4..71e77e7cdb6f 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -82,7 +82,7 @@ struct cgroup_subsys_state { | |||
82 | /* ID for this css, if possible */ | 82 | /* ID for this css, if possible */ |
83 | struct css_id __rcu *id; | 83 | struct css_id __rcu *id; |
84 | 84 | ||
85 | /* Used to put @cgroup->dentry on the last css_put() */ | 85 | /* percpu_ref killing and putting dentry on the last css_put() */ |
86 | struct work_struct destroy_work; | 86 | struct work_struct destroy_work; |
87 | }; | 87 | }; |
88 | 88 | ||
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 174f4c3d72ef..3c4c4b01ffe5 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4355,6 +4355,7 @@ static void offline_css(struct cgroup_subsys_state *css) | |||
4355 | ss->css_offline(css); | 4355 | ss->css_offline(css); |
4356 | 4356 | ||
4357 | css->flags &= ~CSS_ONLINE; | 4357 | css->flags &= ~CSS_ONLINE; |
4358 | css->cgroup->nr_css--; | ||
4358 | } | 4359 | } |
4359 | 4360 | ||
4360 | /* | 4361 | /* |
@@ -4559,14 +4560,29 @@ static void css_killed_work_fn(struct work_struct *work) | |||
4559 | mutex_lock(&cgroup_mutex); | 4560 | mutex_lock(&cgroup_mutex); |
4560 | 4561 | ||
4561 | /* | 4562 | /* |
4563 | * css_tryget() is guaranteed to fail now. Tell subsystems to | ||
4564 | * initate destruction. | ||
4565 | */ | ||
4566 | offline_css(css); | ||
4567 | |||
4568 | /* | ||
4562 | * If @cgrp is marked dead, it's waiting for refs of all css's to | 4569 | * If @cgrp is marked dead, it's waiting for refs of all css's to |
4563 | * be disabled before proceeding to the second phase of cgroup | 4570 | * be disabled before proceeding to the second phase of cgroup |
4564 | * destruction. If we are the last one, kick it off. | 4571 | * destruction. If we are the last one, kick it off. |
4565 | */ | 4572 | */ |
4566 | if (!--cgrp->nr_css && cgroup_is_dead(cgrp)) | 4573 | if (!cgrp->nr_css && cgroup_is_dead(cgrp)) |
4567 | cgroup_destroy_css_killed(cgrp); | 4574 | cgroup_destroy_css_killed(cgrp); |
4568 | 4575 | ||
4569 | mutex_unlock(&cgroup_mutex); | 4576 | mutex_unlock(&cgroup_mutex); |
4577 | |||
4578 | /* | ||
4579 | * Put the css refs from kill_css(). Each css holds an extra | ||
4580 | * reference to the cgroup's dentry and cgroup removal proceeds | ||
4581 | * regardless of css refs. On the last put of each css, whenever | ||
4582 | * that may be, the extra dentry ref is put so that dentry | ||
4583 | * destruction happens only after all css's are released. | ||
4584 | */ | ||
4585 | css_put(css); | ||
4570 | } | 4586 | } |
4571 | 4587 | ||
4572 | /* css kill confirmation processing requires process context, bounce */ | 4588 | /* css kill confirmation processing requires process context, bounce */ |
@@ -4633,11 +4649,10 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4633 | * as killed on all CPUs on return. | 4649 | * as killed on all CPUs on return. |
4634 | * | 4650 | * |
4635 | * Use percpu_ref_kill_and_confirm() to get notifications as each | 4651 | * Use percpu_ref_kill_and_confirm() to get notifications as each |
4636 | * css is confirmed to be seen as killed on all CPUs. The | 4652 | * css is confirmed to be seen as killed on all CPUs. |
4637 | * notification callback keeps track of the number of css's to be | 4653 | * cgroup_destroy_css_killed() will be invoked to perform the rest |
4638 | * killed and invokes cgroup_destroy_css_killed() to perform the | 4654 | * of destruction once the percpu refs of all css's are confirmed |
4639 | * rest of destruction once the percpu refs of all css's are | 4655 | * to be killed. |
4640 | * confirmed to be killed. | ||
4641 | */ | 4656 | */ |
4642 | for_each_root_subsys(cgrp->root, ss) { | 4657 | for_each_root_subsys(cgrp->root, ss) { |
4643 | struct cgroup_subsys_state *css = cgroup_css(cgrp, ss->subsys_id); | 4658 | struct cgroup_subsys_state *css = cgroup_css(cgrp, ss->subsys_id); |
@@ -4704,36 +4719,17 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4704 | * @work: cgroup->destroy_free_work | 4719 | * @work: cgroup->destroy_free_work |
4705 | * | 4720 | * |
4706 | * This function is invoked from a work item for a cgroup which is being | 4721 | * This function is invoked from a work item for a cgroup which is being |
4707 | * destroyed after the percpu refcnts of all css's are guaranteed to be | 4722 | * destroyed after all css's are offlined and performs the rest of |
4708 | * seen as killed on all CPUs, and performs the rest of destruction. This | 4723 | * destruction. This is the second step of destruction described in the |
4709 | * is the second step of destruction described in the comment above | 4724 | * comment above cgroup_destroy_locked(). |
4710 | * cgroup_destroy_locked(). | ||
4711 | */ | 4725 | */ |
4712 | static void cgroup_destroy_css_killed(struct cgroup *cgrp) | 4726 | static void cgroup_destroy_css_killed(struct cgroup *cgrp) |
4713 | { | 4727 | { |
4714 | struct cgroup *parent = cgrp->parent; | 4728 | struct cgroup *parent = cgrp->parent; |
4715 | struct dentry *d = cgrp->dentry; | 4729 | struct dentry *d = cgrp->dentry; |
4716 | struct cgroup_subsys *ss; | ||
4717 | 4730 | ||
4718 | lockdep_assert_held(&cgroup_mutex); | 4731 | lockdep_assert_held(&cgroup_mutex); |
4719 | 4732 | ||
4720 | /* | ||
4721 | * css_tryget() is guaranteed to fail now. Tell subsystems to | ||
4722 | * initate destruction. | ||
4723 | */ | ||
4724 | for_each_root_subsys(cgrp->root, ss) | ||
4725 | offline_css(cgroup_css(cgrp, ss->subsys_id)); | ||
4726 | |||
4727 | /* | ||
4728 | * Put the css refs from cgroup_destroy_locked(). Each css holds | ||
4729 | * an extra reference to the cgroup's dentry and cgroup removal | ||
4730 | * proceeds regardless of css refs. On the last put of each css, | ||
4731 | * whenever that may be, the extra dentry ref is put so that dentry | ||
4732 | * destruction happens only after all css's are released. | ||
4733 | */ | ||
4734 | for_each_root_subsys(cgrp->root, ss) | ||
4735 | css_put(cgroup_css(cgrp, ss->subsys_id)); | ||
4736 | |||
4737 | /* delete this cgroup from parent->children */ | 4733 | /* delete this cgroup from parent->children */ |
4738 | list_del_rcu(&cgrp->sibling); | 4734 | list_del_rcu(&cgrp->sibling); |
4739 | 4735 | ||