diff options
author | Li Zefan <lizefan@huawei.com> | 2013-01-09 22:49:27 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-01-10 15:10:31 -0500 |
commit | 0ac801fe07374148714b5ef53df90ac5b1673c0c (patch) | |
tree | aad528311f4d876c0b8e3750d9cb7b0e072b2935 /kernel/cgroup.c | |
parent | 799105d514384b80cbe3182dbcb4ed30aa07e1f5 (diff) |
cgroup: use new hashtable implementation
Switch cgroup to use the new hashtable implementation. No functional changes.
Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 92 |
1 files changed, 39 insertions, 53 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 6643f7053454..54b39081ac04 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -52,7 +52,7 @@ | |||
52 | #include <linux/module.h> | 52 | #include <linux/module.h> |
53 | #include <linux/delayacct.h> | 53 | #include <linux/delayacct.h> |
54 | #include <linux/cgroupstats.h> | 54 | #include <linux/cgroupstats.h> |
55 | #include <linux/hash.h> | 55 | #include <linux/hashtable.h> |
56 | #include <linux/namei.h> | 56 | #include <linux/namei.h> |
57 | #include <linux/pid_namespace.h> | 57 | #include <linux/pid_namespace.h> |
58 | #include <linux/idr.h> | 58 | #include <linux/idr.h> |
@@ -376,22 +376,18 @@ static int css_set_count; | |||
376 | * account cgroups in empty hierarchies. | 376 | * account cgroups in empty hierarchies. |
377 | */ | 377 | */ |
378 | #define CSS_SET_HASH_BITS 7 | 378 | #define CSS_SET_HASH_BITS 7 |
379 | #define CSS_SET_TABLE_SIZE (1 << CSS_SET_HASH_BITS) | 379 | static DEFINE_HASHTABLE(css_set_table, CSS_SET_HASH_BITS); |
380 | static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE]; | ||
381 | 380 | ||
382 | static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]) | 381 | static unsigned long css_set_hash(struct cgroup_subsys_state *css[]) |
383 | { | 382 | { |
384 | int i; | 383 | int i; |
385 | int index; | 384 | unsigned long key = 0UL; |
386 | unsigned long tmp = 0UL; | ||
387 | 385 | ||
388 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) | 386 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) |
389 | tmp += (unsigned long)css[i]; | 387 | key += (unsigned long)css[i]; |
390 | tmp = (tmp >> 16) ^ tmp; | 388 | key = (key >> 16) ^ key; |
391 | 389 | ||
392 | index = hash_long(tmp, CSS_SET_HASH_BITS); | 390 | return key; |
393 | |||
394 | return &css_set_table[index]; | ||
395 | } | 391 | } |
396 | 392 | ||
397 | /* We don't maintain the lists running through each css_set to its | 393 | /* We don't maintain the lists running through each css_set to its |
@@ -418,7 +414,7 @@ static void __put_css_set(struct css_set *cg, int taskexit) | |||
418 | } | 414 | } |
419 | 415 | ||
420 | /* This css_set is dead. unlink it and release cgroup refcounts */ | 416 | /* This css_set is dead. unlink it and release cgroup refcounts */ |
421 | hlist_del(&cg->hlist); | 417 | hash_del(&cg->hlist); |
422 | css_set_count--; | 418 | css_set_count--; |
423 | 419 | ||
424 | list_for_each_entry_safe(link, saved_link, &cg->cg_links, | 420 | list_for_each_entry_safe(link, saved_link, &cg->cg_links, |
@@ -550,9 +546,9 @@ static struct css_set *find_existing_css_set( | |||
550 | { | 546 | { |
551 | int i; | 547 | int i; |
552 | struct cgroupfs_root *root = cgrp->root; | 548 | struct cgroupfs_root *root = cgrp->root; |
553 | struct hlist_head *hhead; | ||
554 | struct hlist_node *node; | 549 | struct hlist_node *node; |
555 | struct css_set *cg; | 550 | struct css_set *cg; |
551 | unsigned long key; | ||
556 | 552 | ||
557 | /* | 553 | /* |
558 | * Build the set of subsystem state objects that we want to see in the | 554 | * Build the set of subsystem state objects that we want to see in the |
@@ -572,8 +568,8 @@ static struct css_set *find_existing_css_set( | |||
572 | } | 568 | } |
573 | } | 569 | } |
574 | 570 | ||
575 | hhead = css_set_hash(template); | 571 | key = css_set_hash(template); |
576 | hlist_for_each_entry(cg, node, hhead, hlist) { | 572 | hash_for_each_possible(css_set_table, cg, node, hlist, key) { |
577 | if (!compare_css_sets(cg, oldcg, cgrp, template)) | 573 | if (!compare_css_sets(cg, oldcg, cgrp, template)) |
578 | continue; | 574 | continue; |
579 | 575 | ||
@@ -657,8 +653,8 @@ static struct css_set *find_css_set( | |||
657 | 653 | ||
658 | struct list_head tmp_cg_links; | 654 | struct list_head tmp_cg_links; |
659 | 655 | ||
660 | struct hlist_head *hhead; | ||
661 | struct cg_cgroup_link *link; | 656 | struct cg_cgroup_link *link; |
657 | unsigned long key; | ||
662 | 658 | ||
663 | /* First see if we already have a cgroup group that matches | 659 | /* First see if we already have a cgroup group that matches |
664 | * the desired set */ | 660 | * the desired set */ |
@@ -704,8 +700,8 @@ static struct css_set *find_css_set( | |||
704 | css_set_count++; | 700 | css_set_count++; |
705 | 701 | ||
706 | /* Add this cgroup group to the hash table */ | 702 | /* Add this cgroup group to the hash table */ |
707 | hhead = css_set_hash(res->subsys); | 703 | key = css_set_hash(res->subsys); |
708 | hlist_add_head(&res->hlist, hhead); | 704 | hash_add(css_set_table, &res->hlist, key); |
709 | 705 | ||
710 | write_unlock(&css_set_lock); | 706 | write_unlock(&css_set_lock); |
711 | 707 | ||
@@ -1597,6 +1593,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1597 | struct cgroupfs_root *existing_root; | 1593 | struct cgroupfs_root *existing_root; |
1598 | const struct cred *cred; | 1594 | const struct cred *cred; |
1599 | int i; | 1595 | int i; |
1596 | struct hlist_node *node; | ||
1597 | struct css_set *cg; | ||
1600 | 1598 | ||
1601 | BUG_ON(sb->s_root != NULL); | 1599 | BUG_ON(sb->s_root != NULL); |
1602 | 1600 | ||
@@ -1650,14 +1648,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1650 | /* Link the top cgroup in this hierarchy into all | 1648 | /* Link the top cgroup in this hierarchy into all |
1651 | * the css_set objects */ | 1649 | * the css_set objects */ |
1652 | write_lock(&css_set_lock); | 1650 | write_lock(&css_set_lock); |
1653 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) { | 1651 | hash_for_each(css_set_table, i, node, cg, hlist) |
1654 | struct hlist_head *hhead = &css_set_table[i]; | 1652 | link_css_set(&tmp_cg_links, cg, root_cgrp); |
1655 | struct hlist_node *node; | ||
1656 | struct css_set *cg; | ||
1657 | |||
1658 | hlist_for_each_entry(cg, node, hhead, hlist) | ||
1659 | link_css_set(&tmp_cg_links, cg, root_cgrp); | ||
1660 | } | ||
1661 | write_unlock(&css_set_lock); | 1653 | write_unlock(&css_set_lock); |
1662 | 1654 | ||
1663 | free_cg_links(&tmp_cg_links); | 1655 | free_cg_links(&tmp_cg_links); |
@@ -4464,6 +4456,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
4464 | { | 4456 | { |
4465 | struct cgroup_subsys_state *css; | 4457 | struct cgroup_subsys_state *css; |
4466 | int i, ret; | 4458 | int i, ret; |
4459 | struct hlist_node *node, *tmp; | ||
4460 | struct css_set *cg; | ||
4461 | unsigned long key; | ||
4467 | 4462 | ||
4468 | /* check name and function validity */ | 4463 | /* check name and function validity */ |
4469 | if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN || | 4464 | if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN || |
@@ -4529,23 +4524,17 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
4529 | * this is all done under the css_set_lock. | 4524 | * this is all done under the css_set_lock. |
4530 | */ | 4525 | */ |
4531 | write_lock(&css_set_lock); | 4526 | write_lock(&css_set_lock); |
4532 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) { | 4527 | hash_for_each_safe(css_set_table, i, node, tmp, cg, hlist) { |
4533 | struct css_set *cg; | 4528 | /* skip entries that we already rehashed */ |
4534 | struct hlist_node *node, *tmp; | 4529 | if (cg->subsys[ss->subsys_id]) |
4535 | struct hlist_head *bucket = &css_set_table[i], *new_bucket; | 4530 | continue; |
4536 | 4531 | /* remove existing entry */ | |
4537 | hlist_for_each_entry_safe(cg, node, tmp, bucket, hlist) { | 4532 | hash_del(&cg->hlist); |
4538 | /* skip entries that we already rehashed */ | 4533 | /* set new value */ |
4539 | if (cg->subsys[ss->subsys_id]) | 4534 | cg->subsys[ss->subsys_id] = css; |
4540 | continue; | 4535 | /* recompute hash and restore entry */ |
4541 | /* remove existing entry */ | 4536 | key = css_set_hash(cg->subsys); |
4542 | hlist_del(&cg->hlist); | 4537 | hash_add(css_set_table, node, key); |
4543 | /* set new value */ | ||
4544 | cg->subsys[ss->subsys_id] = css; | ||
4545 | /* recompute hash and restore entry */ | ||
4546 | new_bucket = css_set_hash(cg->subsys); | ||
4547 | hlist_add_head(&cg->hlist, new_bucket); | ||
4548 | } | ||
4549 | } | 4538 | } |
4550 | write_unlock(&css_set_lock); | 4539 | write_unlock(&css_set_lock); |
4551 | 4540 | ||
@@ -4577,7 +4566,6 @@ EXPORT_SYMBOL_GPL(cgroup_load_subsys); | |||
4577 | void cgroup_unload_subsys(struct cgroup_subsys *ss) | 4566 | void cgroup_unload_subsys(struct cgroup_subsys *ss) |
4578 | { | 4567 | { |
4579 | struct cg_cgroup_link *link; | 4568 | struct cg_cgroup_link *link; |
4580 | struct hlist_head *hhead; | ||
4581 | 4569 | ||
4582 | BUG_ON(ss->module == NULL); | 4570 | BUG_ON(ss->module == NULL); |
4583 | 4571 | ||
@@ -4611,11 +4599,12 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) | |||
4611 | write_lock(&css_set_lock); | 4599 | write_lock(&css_set_lock); |
4612 | list_for_each_entry(link, &dummytop->css_sets, cgrp_link_list) { | 4600 | list_for_each_entry(link, &dummytop->css_sets, cgrp_link_list) { |
4613 | struct css_set *cg = link->cg; | 4601 | struct css_set *cg = link->cg; |
4602 | unsigned long key; | ||
4614 | 4603 | ||
4615 | hlist_del(&cg->hlist); | 4604 | hash_del(&cg->hlist); |
4616 | cg->subsys[ss->subsys_id] = NULL; | 4605 | cg->subsys[ss->subsys_id] = NULL; |
4617 | hhead = css_set_hash(cg->subsys); | 4606 | key = css_set_hash(cg->subsys); |
4618 | hlist_add_head(&cg->hlist, hhead); | 4607 | hash_add(css_set_table, &cg->hlist, key); |
4619 | } | 4608 | } |
4620 | write_unlock(&css_set_lock); | 4609 | write_unlock(&css_set_lock); |
4621 | 4610 | ||
@@ -4657,9 +4646,6 @@ int __init cgroup_init_early(void) | |||
4657 | list_add(&init_css_set_link.cg_link_list, | 4646 | list_add(&init_css_set_link.cg_link_list, |
4658 | &init_css_set.cg_links); | 4647 | &init_css_set.cg_links); |
4659 | 4648 | ||
4660 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) | ||
4661 | INIT_HLIST_HEAD(&css_set_table[i]); | ||
4662 | |||
4663 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 4649 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
4664 | struct cgroup_subsys *ss = subsys[i]; | 4650 | struct cgroup_subsys *ss = subsys[i]; |
4665 | 4651 | ||
@@ -4693,7 +4679,7 @@ int __init cgroup_init(void) | |||
4693 | { | 4679 | { |
4694 | int err; | 4680 | int err; |
4695 | int i; | 4681 | int i; |
4696 | struct hlist_head *hhead; | 4682 | unsigned long key; |
4697 | 4683 | ||
4698 | err = bdi_init(&cgroup_backing_dev_info); | 4684 | err = bdi_init(&cgroup_backing_dev_info); |
4699 | if (err) | 4685 | if (err) |
@@ -4712,8 +4698,8 @@ int __init cgroup_init(void) | |||
4712 | } | 4698 | } |
4713 | 4699 | ||
4714 | /* Add init_css_set to the hash table */ | 4700 | /* Add init_css_set to the hash table */ |
4715 | hhead = css_set_hash(init_css_set.subsys); | 4701 | key = css_set_hash(init_css_set.subsys); |
4716 | hlist_add_head(&init_css_set.hlist, hhead); | 4702 | hash_add(css_set_table, &init_css_set.hlist, key); |
4717 | BUG_ON(!init_root_id(&rootnode)); | 4703 | BUG_ON(!init_root_id(&rootnode)); |
4718 | 4704 | ||
4719 | cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj); | 4705 | cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj); |