diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:37 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:37 -0500 |
commit | 42809dd4225b2f3127a4804314a1b33608620d96 (patch) | |
tree | 7600d71baff46173b9b2c051a3530a4a4b7c9582 /kernel/cgroup.c | |
parent | 02ae7486d05ae6df8395409a4945b2420f1e35c2 (diff) |
cgroup: separate out cgroup_destroy_locked()
Separate out cgroup_destroy_locked() from cgroup_destroy(). This will
be later used in cgroup_create() failure path.
While at it, add lockdep asserts on i_mutex and cgroup_mutex, and move
@d and @parent assignments to their declarations.
This patch doesn't introduce any functional difference.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 5679cb1ce43f..4412d9694f13 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -242,6 +242,8 @@ static DEFINE_SPINLOCK(hierarchy_id_lock); | |||
242 | */ | 242 | */ |
243 | static int need_forkexit_callback __read_mostly; | 243 | static int need_forkexit_callback __read_mostly; |
244 | 244 | ||
245 | static int cgroup_destroy_locked(struct cgroup *cgrp); | ||
246 | |||
245 | #ifdef CONFIG_PROVE_LOCKING | 247 | #ifdef CONFIG_PROVE_LOCKING |
246 | int cgroup_lock_is_held(void) | 248 | int cgroup_lock_is_held(void) |
247 | { | 249 | { |
@@ -4209,22 +4211,20 @@ static int cgroup_has_css_refs(struct cgroup *cgrp) | |||
4209 | return 0; | 4211 | return 0; |
4210 | } | 4212 | } |
4211 | 4213 | ||
4212 | static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | 4214 | static int cgroup_destroy_locked(struct cgroup *cgrp) |
4215 | __releases(&cgroup_mutex) __acquires(&cgroup_mutex) | ||
4213 | { | 4216 | { |
4214 | struct cgroup *cgrp = dentry->d_fsdata; | 4217 | struct dentry *d = cgrp->dentry; |
4215 | struct dentry *d; | 4218 | struct cgroup *parent = cgrp->parent; |
4216 | struct cgroup *parent; | ||
4217 | DEFINE_WAIT(wait); | 4219 | DEFINE_WAIT(wait); |
4218 | struct cgroup_event *event, *tmp; | 4220 | struct cgroup_event *event, *tmp; |
4219 | struct cgroup_subsys *ss; | 4221 | struct cgroup_subsys *ss; |
4220 | 4222 | ||
4221 | /* the vfs holds both inode->i_mutex already */ | 4223 | lockdep_assert_held(&d->d_inode->i_mutex); |
4222 | mutex_lock(&cgroup_mutex); | 4224 | lockdep_assert_held(&cgroup_mutex); |
4223 | parent = cgrp->parent; | 4225 | |
4224 | if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) { | 4226 | if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) |
4225 | mutex_unlock(&cgroup_mutex); | ||
4226 | return -EBUSY; | 4227 | return -EBUSY; |
4227 | } | ||
4228 | 4228 | ||
4229 | /* | 4229 | /* |
4230 | * Block new css_tryget() by deactivating refcnt and mark @cgrp | 4230 | * Block new css_tryget() by deactivating refcnt and mark @cgrp |
@@ -4243,7 +4243,9 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
4243 | /* | 4243 | /* |
4244 | * Tell subsystems to initate destruction. pre_destroy() should be | 4244 | * Tell subsystems to initate destruction. pre_destroy() should be |
4245 | * called with cgroup_mutex unlocked. See 3fa59dfbc3 ("cgroup: fix | 4245 | * called with cgroup_mutex unlocked. See 3fa59dfbc3 ("cgroup: fix |
4246 | * potential deadlock in pre_destroy") for details. | 4246 | * potential deadlock in pre_destroy") for details. This temporary |
4247 | * unlocking should go away once cgroup_mutex is unexported from | ||
4248 | * controllers. | ||
4247 | */ | 4249 | */ |
4248 | mutex_unlock(&cgroup_mutex); | 4250 | mutex_unlock(&cgroup_mutex); |
4249 | for_each_subsys(cgrp->root, ss) | 4251 | for_each_subsys(cgrp->root, ss) |
@@ -4268,11 +4270,9 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
4268 | 4270 | ||
4269 | /* delete this cgroup from parent->children */ | 4271 | /* delete this cgroup from parent->children */ |
4270 | list_del_rcu(&cgrp->sibling); | 4272 | list_del_rcu(&cgrp->sibling); |
4271 | |||
4272 | list_del_init(&cgrp->allcg_node); | 4273 | list_del_init(&cgrp->allcg_node); |
4273 | 4274 | ||
4274 | d = dget(cgrp->dentry); | 4275 | dget(d); |
4275 | |||
4276 | cgroup_d_remove_dir(d); | 4276 | cgroup_d_remove_dir(d); |
4277 | dput(d); | 4277 | dput(d); |
4278 | 4278 | ||
@@ -4293,10 +4293,20 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
4293 | } | 4293 | } |
4294 | spin_unlock(&cgrp->event_list_lock); | 4294 | spin_unlock(&cgrp->event_list_lock); |
4295 | 4295 | ||
4296 | mutex_unlock(&cgroup_mutex); | ||
4297 | return 0; | 4296 | return 0; |
4298 | } | 4297 | } |
4299 | 4298 | ||
4299 | static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | ||
4300 | { | ||
4301 | int ret; | ||
4302 | |||
4303 | mutex_lock(&cgroup_mutex); | ||
4304 | ret = cgroup_destroy_locked(dentry->d_fsdata); | ||
4305 | mutex_unlock(&cgroup_mutex); | ||
4306 | |||
4307 | return ret; | ||
4308 | } | ||
4309 | |||
4300 | static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss) | 4310 | static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss) |
4301 | { | 4311 | { |
4302 | INIT_LIST_HEAD(&ss->cftsets); | 4312 | INIT_LIST_HEAD(&ss->cftsets); |