diff options
| author | Tejun Heo <tj@kernel.org> | 2014-06-28 08:10:14 -0400 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2014-06-28 08:10:14 -0400 |
| commit | 9a1049da9bd2cd83fe11d46433e603c193aa9c71 (patch) | |
| tree | 007d2843abf0f064c294659334e69e297ffc2b74 /kernel | |
| parent | 7d742075120deb831c7b94c268ca20d409e91d60 (diff) | |
percpu-refcount: require percpu_ref to be exited explicitly
Currently, a percpu_ref undoes percpu_ref_init() automatically by
freeing the allocated percpu area when the percpu_ref is killed.
While seemingly convenient, this has the following niggles.
* It's impossible to re-init a released reference counter without
going through re-allocation.
* In the similar vein, it's impossible to initialize a percpu_ref
count with static percpu variables.
* We need and have an explicit destructor anyway for failure paths -
percpu_ref_cancel_init().
This patch removes the automatic percpu counter freeing in
percpu_ref_kill_rcu() and repurposes percpu_ref_cancel_init() into a
generic destructor now named percpu_ref_exit(). percpu_ref_destroy()
is considered but it gets confusing with percpu_ref_kill() while
"exit" clearly indicates that it's the counterpart of
percpu_ref_init().
All percpu_ref_cancel_init() users are updated to invoke
percpu_ref_exit() instead and explicit percpu_ref_exit() calls are
added to the destruction path of all percpu_ref users.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Benjamin LaHaise <bcrl@kvack.org>
Cc: Kent Overstreet <kmo@daterainc.com>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Cc: Nicholas A. Bellinger <nab@linux-iscsi.org>
Cc: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 7868fc3c0bc5..c06aa5e257a8 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -1638,7 +1638,7 @@ destroy_root: | |||
| 1638 | exit_root_id: | 1638 | exit_root_id: |
| 1639 | cgroup_exit_root_id(root); | 1639 | cgroup_exit_root_id(root); |
| 1640 | cancel_ref: | 1640 | cancel_ref: |
| 1641 | percpu_ref_cancel_init(&root_cgrp->self.refcnt); | 1641 | percpu_ref_exit(&root_cgrp->self.refcnt); |
| 1642 | out: | 1642 | out: |
| 1643 | free_cgrp_cset_links(&tmp_links); | 1643 | free_cgrp_cset_links(&tmp_links); |
| 1644 | return ret; | 1644 | return ret; |
| @@ -4133,6 +4133,8 @@ static void css_free_work_fn(struct work_struct *work) | |||
| 4133 | container_of(work, struct cgroup_subsys_state, destroy_work); | 4133 | container_of(work, struct cgroup_subsys_state, destroy_work); |
| 4134 | struct cgroup *cgrp = css->cgroup; | 4134 | struct cgroup *cgrp = css->cgroup; |
| 4135 | 4135 | ||
| 4136 | percpu_ref_exit(&css->refcnt); | ||
| 4137 | |||
| 4136 | if (css->ss) { | 4138 | if (css->ss) { |
| 4137 | /* css free path */ | 4139 | /* css free path */ |
| 4138 | if (css->parent) | 4140 | if (css->parent) |
| @@ -4330,7 +4332,7 @@ err_list_del: | |||
| 4330 | err_free_id: | 4332 | err_free_id: |
| 4331 | cgroup_idr_remove(&ss->css_idr, css->id); | 4333 | cgroup_idr_remove(&ss->css_idr, css->id); |
| 4332 | err_free_percpu_ref: | 4334 | err_free_percpu_ref: |
| 4333 | percpu_ref_cancel_init(&css->refcnt); | 4335 | percpu_ref_exit(&css->refcnt); |
| 4334 | err_free_css: | 4336 | err_free_css: |
| 4335 | call_rcu(&css->rcu_head, css_free_rcu_fn); | 4337 | call_rcu(&css->rcu_head, css_free_rcu_fn); |
| 4336 | return err; | 4338 | return err; |
| @@ -4441,7 +4443,7 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, | |||
| 4441 | out_free_id: | 4443 | out_free_id: |
| 4442 | cgroup_idr_remove(&root->cgroup_idr, cgrp->id); | 4444 | cgroup_idr_remove(&root->cgroup_idr, cgrp->id); |
| 4443 | out_cancel_ref: | 4445 | out_cancel_ref: |
| 4444 | percpu_ref_cancel_init(&cgrp->self.refcnt); | 4446 | percpu_ref_exit(&cgrp->self.refcnt); |
| 4445 | out_free_cgrp: | 4447 | out_free_cgrp: |
| 4446 | kfree(cgrp); | 4448 | kfree(cgrp); |
| 4447 | out_unlock: | 4449 | out_unlock: |
