diff options
author | Li Zefan <lizefan@huawei.com> | 2013-07-30 21:50:50 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-07-31 07:47:34 -0400 |
commit | 4e96ee8e981b5140a2bcc5fff0d5c0eef39a62ee (patch) | |
tree | b6ef292c7e0aa59b29ff2827bdee631d23b02eaa /kernel/cgroup.c | |
parent | 6f4b7e632d78c2d91502211c430722cc66428492 (diff) |
cgroup: convert cgroup_ida to cgroup_idr
This enables us to lookup a cgroup by its id.
v4:
- add a comment for idr_remove() in cgroup_offline_fn().
v3:
- on success, idr_alloc() returns the id but not 0, so fix the BUG_ON()
in cgroup_init().
- pass the right value to idr_alloc() so that the id for dummy cgroup is 0.
Signed-off-by: Li Zefan <lizefan@huawei.com>
Reviewed-by: Michal Hocko <mhocko@suse.cz>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9577bebe2546..3f6593333525 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -866,8 +866,6 @@ static void cgroup_free_fn(struct work_struct *work) | |||
866 | */ | 866 | */ |
867 | dput(cgrp->parent->dentry); | 867 | dput(cgrp->parent->dentry); |
868 | 868 | ||
869 | ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id); | ||
870 | |||
871 | /* | 869 | /* |
872 | * Drop the active superblock reference that we took when we | 870 | * Drop the active superblock reference that we took when we |
873 | * created the cgroup. This will free cgrp->root, if we are | 871 | * created the cgroup. This will free cgrp->root, if we are |
@@ -1379,6 +1377,7 @@ static void init_cgroup_root(struct cgroupfs_root *root) | |||
1379 | cgrp->root = root; | 1377 | cgrp->root = root; |
1380 | RCU_INIT_POINTER(cgrp->name, &root_cgroup_name); | 1378 | RCU_INIT_POINTER(cgrp->name, &root_cgroup_name); |
1381 | init_cgroup_housekeeping(cgrp); | 1379 | init_cgroup_housekeeping(cgrp); |
1380 | idr_init(&root->cgroup_idr); | ||
1382 | } | 1381 | } |
1383 | 1382 | ||
1384 | static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end) | 1383 | static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end) |
@@ -1451,7 +1450,6 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts) | |||
1451 | */ | 1450 | */ |
1452 | root->subsys_mask = opts->subsys_mask; | 1451 | root->subsys_mask = opts->subsys_mask; |
1453 | root->flags = opts->flags; | 1452 | root->flags = opts->flags; |
1454 | ida_init(&root->cgroup_ida); | ||
1455 | if (opts->release_agent) | 1453 | if (opts->release_agent) |
1456 | strcpy(root->release_agent_path, opts->release_agent); | 1454 | strcpy(root->release_agent_path, opts->release_agent); |
1457 | if (opts->name) | 1455 | if (opts->name) |
@@ -1467,7 +1465,7 @@ static void cgroup_free_root(struct cgroupfs_root *root) | |||
1467 | /* hierarhcy ID shoulid already have been released */ | 1465 | /* hierarhcy ID shoulid already have been released */ |
1468 | WARN_ON_ONCE(root->hierarchy_id); | 1466 | WARN_ON_ONCE(root->hierarchy_id); |
1469 | 1467 | ||
1470 | ida_destroy(&root->cgroup_ida); | 1468 | idr_destroy(&root->cgroup_idr); |
1471 | kfree(root); | 1469 | kfree(root); |
1472 | } | 1470 | } |
1473 | } | 1471 | } |
@@ -1582,6 +1580,11 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1582 | mutex_lock(&cgroup_mutex); | 1580 | mutex_lock(&cgroup_mutex); |
1583 | mutex_lock(&cgroup_root_mutex); | 1581 | mutex_lock(&cgroup_root_mutex); |
1584 | 1582 | ||
1583 | root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp, | ||
1584 | 0, 1, GFP_KERNEL); | ||
1585 | if (root_cgrp->id < 0) | ||
1586 | goto unlock_drop; | ||
1587 | |||
1585 | /* Check for name clashes with existing mounts */ | 1588 | /* Check for name clashes with existing mounts */ |
1586 | ret = -EBUSY; | 1589 | ret = -EBUSY; |
1587 | if (strlen(root->name)) | 1590 | if (strlen(root->name)) |
@@ -4253,7 +4256,11 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4253 | goto err_free_cgrp; | 4256 | goto err_free_cgrp; |
4254 | rcu_assign_pointer(cgrp->name, name); | 4257 | rcu_assign_pointer(cgrp->name, name); |
4255 | 4258 | ||
4256 | cgrp->id = ida_simple_get(&root->cgroup_ida, 1, 0, GFP_KERNEL); | 4259 | /* |
4260 | * Temporarily set the pointer to NULL, so idr_find() won't return | ||
4261 | * a half-baked cgroup. | ||
4262 | */ | ||
4263 | cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); | ||
4257 | if (cgrp->id < 0) | 4264 | if (cgrp->id < 0) |
4258 | goto err_free_name; | 4265 | goto err_free_name; |
4259 | 4266 | ||
@@ -4351,6 +4358,8 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4351 | } | 4358 | } |
4352 | } | 4359 | } |
4353 | 4360 | ||
4361 | idr_replace(&root->cgroup_idr, cgrp, cgrp->id); | ||
4362 | |||
4354 | err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true); | 4363 | err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true); |
4355 | if (err) | 4364 | if (err) |
4356 | goto err_destroy; | 4365 | goto err_destroy; |
@@ -4377,7 +4386,7 @@ err_free_all: | |||
4377 | /* Release the reference count that we took on the superblock */ | 4386 | /* Release the reference count that we took on the superblock */ |
4378 | deactivate_super(sb); | 4387 | deactivate_super(sb); |
4379 | err_free_id: | 4388 | err_free_id: |
4380 | ida_simple_remove(&root->cgroup_ida, cgrp->id); | 4389 | idr_remove(&root->cgroup_idr, cgrp->id); |
4381 | err_free_name: | 4390 | err_free_name: |
4382 | kfree(rcu_dereference_raw(cgrp->name)); | 4391 | kfree(rcu_dereference_raw(cgrp->name)); |
4383 | err_free_cgrp: | 4392 | err_free_cgrp: |
@@ -4570,6 +4579,14 @@ static void cgroup_offline_fn(struct work_struct *work) | |||
4570 | /* delete this cgroup from parent->children */ | 4579 | /* delete this cgroup from parent->children */ |
4571 | list_del_rcu(&cgrp->sibling); | 4580 | list_del_rcu(&cgrp->sibling); |
4572 | 4581 | ||
4582 | /* | ||
4583 | * We should remove the cgroup object from idr before its grace | ||
4584 | * period starts, so we won't be looking up a cgroup while the | ||
4585 | * cgroup is being freed. | ||
4586 | */ | ||
4587 | idr_remove(&cgrp->root->cgroup_idr, cgrp->id); | ||
4588 | cgrp->id = -1; | ||
4589 | |||
4573 | dput(d); | 4590 | dput(d); |
4574 | 4591 | ||
4575 | set_bit(CGRP_RELEASABLE, &parent->flags); | 4592 | set_bit(CGRP_RELEASABLE, &parent->flags); |
@@ -4895,6 +4912,10 @@ int __init cgroup_init(void) | |||
4895 | 4912 | ||
4896 | BUG_ON(cgroup_init_root_id(&cgroup_dummy_root, 0, 1)); | 4913 | BUG_ON(cgroup_init_root_id(&cgroup_dummy_root, 0, 1)); |
4897 | 4914 | ||
4915 | err = idr_alloc(&cgroup_dummy_root.cgroup_idr, cgroup_dummy_top, | ||
4916 | 0, 1, GFP_KERNEL); | ||
4917 | BUG_ON(err < 0); | ||
4918 | |||
4898 | mutex_unlock(&cgroup_root_mutex); | 4919 | mutex_unlock(&cgroup_root_mutex); |
4899 | mutex_unlock(&cgroup_mutex); | 4920 | mutex_unlock(&cgroup_mutex); |
4900 | 4921 | ||