aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2013-07-30 21:50:50 -0400
committerTejun Heo <tj@kernel.org>2013-07-31 07:47:34 -0400
commit4e96ee8e981b5140a2bcc5fff0d5c0eef39a62ee (patch)
treeb6ef292c7e0aa59b29ff2827bdee631d23b02eaa
parent6f4b7e632d78c2d91502211c430722cc66428492 (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>
-rw-r--r--include/linux/cgroup.h4
-rw-r--r--kernel/cgroup.c33
2 files changed, 29 insertions, 8 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 00a7e07a1567..cca570e188fb 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -161,7 +161,7 @@ struct cgroup_name {
161struct cgroup { 161struct cgroup {
162 unsigned long flags; /* "unsigned long" so bitops work */ 162 unsigned long flags; /* "unsigned long" so bitops work */
163 163
164 int id; /* ida allocated in-hierarchy ID */ 164 int id; /* idr allocated in-hierarchy ID */
165 165
166 /* 166 /*
167 * We link our 'sibling' struct into our parent's 'children'. 167 * We link our 'sibling' struct into our parent's 'children'.
@@ -322,7 +322,7 @@ struct cgroupfs_root {
322 unsigned long flags; 322 unsigned long flags;
323 323
324 /* IDs for cgroups in this hierarchy */ 324 /* IDs for cgroups in this hierarchy */
325 struct ida cgroup_ida; 325 struct idr cgroup_idr;
326 326
327 /* The path to use for release notifications. */ 327 /* The path to use for release notifications. */
328 char release_agent_path[PATH_MAX]; 328 char release_agent_path[PATH_MAX];
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
1384static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end) 1383static 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);
4379err_free_id: 4388err_free_id:
4380 ida_simple_remove(&root->cgroup_ida, cgrp->id); 4389 idr_remove(&root->cgroup_idr, cgrp->id);
4381err_free_name: 4390err_free_name:
4382 kfree(rcu_dereference_raw(cgrp->name)); 4391 kfree(rcu_dereference_raw(cgrp->name));
4383err_free_cgrp: 4392err_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