diff options
Diffstat (limited to 'kernel/cgroup.c')
| -rw-r--r-- | kernel/cgroup.c | 435 |
1 files changed, 401 insertions, 34 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9edb5c4b79b..382109b5bae 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -94,7 +94,6 @@ struct cgroupfs_root { | |||
| 94 | char release_agent_path[PATH_MAX]; | 94 | char release_agent_path[PATH_MAX]; |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | |||
| 98 | /* | 97 | /* |
| 99 | * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the | 98 | * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the |
| 100 | * subsystems that are otherwise unattached - it never has more than a | 99 | * subsystems that are otherwise unattached - it never has more than a |
| @@ -102,6 +101,39 @@ struct cgroupfs_root { | |||
| 102 | */ | 101 | */ |
| 103 | static struct cgroupfs_root rootnode; | 102 | static struct cgroupfs_root rootnode; |
| 104 | 103 | ||
| 104 | /* | ||
| 105 | * CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when | ||
| 106 | * cgroup_subsys->use_id != 0. | ||
| 107 | */ | ||
| 108 | #define CSS_ID_MAX (65535) | ||
| 109 | struct css_id { | ||
| 110 | /* | ||
| 111 | * The css to which this ID points. This pointer is set to valid value | ||
| 112 | * after cgroup is populated. If cgroup is removed, this will be NULL. | ||
| 113 | * This pointer is expected to be RCU-safe because destroy() | ||
| 114 | * is called after synchronize_rcu(). But for safe use, css_is_removed() | ||
| 115 | * css_tryget() should be used for avoiding race. | ||
| 116 | */ | ||
| 117 | struct cgroup_subsys_state *css; | ||
| 118 | /* | ||
| 119 | * ID of this css. | ||
| 120 | */ | ||
| 121 | unsigned short id; | ||
| 122 | /* | ||
| 123 | * Depth in hierarchy which this ID belongs to. | ||
| 124 | */ | ||
| 125 | unsigned short depth; | ||
| 126 | /* | ||
| 127 | * ID is freed by RCU. (and lookup routine is RCU safe.) | ||
| 128 | */ | ||
| 129 | struct rcu_head rcu_head; | ||
| 130 | /* | ||
| 131 | * Hierarchy of CSS ID belongs to. | ||
| 132 | */ | ||
| 133 | unsigned short stack[0]; /* Array of Length (depth+1) */ | ||
| 134 | }; | ||
| 135 | |||
| 136 | |||
| 105 | /* The list of hierarchy roots */ | 137 | /* The list of hierarchy roots */ |
| 106 | 138 | ||
| 107 | static LIST_HEAD(roots); | 139 | static LIST_HEAD(roots); |
| @@ -185,6 +217,8 @@ struct cg_cgroup_link { | |||
| 185 | static struct css_set init_css_set; | 217 | static struct css_set init_css_set; |
| 186 | static struct cg_cgroup_link init_css_set_link; | 218 | static struct cg_cgroup_link init_css_set_link; |
| 187 | 219 | ||
| 220 | static int cgroup_subsys_init_idr(struct cgroup_subsys *ss); | ||
| 221 | |||
| 188 | /* css_set_lock protects the list of css_set objects, and the | 222 | /* css_set_lock protects the list of css_set objects, and the |
| 189 | * chain of tasks off each css_set. Nests outside task->alloc_lock | 223 | * chain of tasks off each css_set. Nests outside task->alloc_lock |
| 190 | * due to cgroup_iter_start() */ | 224 | * due to cgroup_iter_start() */ |
| @@ -567,6 +601,9 @@ static struct backing_dev_info cgroup_backing_dev_info = { | |||
| 567 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, | 601 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, |
| 568 | }; | 602 | }; |
| 569 | 603 | ||
| 604 | static int alloc_css_id(struct cgroup_subsys *ss, | ||
| 605 | struct cgroup *parent, struct cgroup *child); | ||
| 606 | |||
| 570 | static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb) | 607 | static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb) |
| 571 | { | 608 | { |
| 572 | struct inode *inode = new_inode(sb); | 609 | struct inode *inode = new_inode(sb); |
| @@ -585,13 +622,18 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb) | |||
| 585 | * Call subsys's pre_destroy handler. | 622 | * Call subsys's pre_destroy handler. |
| 586 | * This is called before css refcnt check. | 623 | * This is called before css refcnt check. |
| 587 | */ | 624 | */ |
| 588 | static void cgroup_call_pre_destroy(struct cgroup *cgrp) | 625 | static int cgroup_call_pre_destroy(struct cgroup *cgrp) |
| 589 | { | 626 | { |
| 590 | struct cgroup_subsys *ss; | 627 | struct cgroup_subsys *ss; |
| 628 | int ret = 0; | ||
| 629 | |||
| 591 | for_each_subsys(cgrp->root, ss) | 630 | for_each_subsys(cgrp->root, ss) |
| 592 | if (ss->pre_destroy) | 631 | if (ss->pre_destroy) { |
| 593 | ss->pre_destroy(ss, cgrp); | 632 | ret = ss->pre_destroy(ss, cgrp); |
| 594 | return; | 633 | if (ret) |
| 634 | break; | ||
| 635 | } | ||
| 636 | return ret; | ||
| 595 | } | 637 | } |
| 596 | 638 | ||
| 597 | static void free_cgroup_rcu(struct rcu_head *obj) | 639 | static void free_cgroup_rcu(struct rcu_head *obj) |
| @@ -685,6 +727,22 @@ static void cgroup_d_remove_dir(struct dentry *dentry) | |||
| 685 | remove_dir(dentry); | 727 | remove_dir(dentry); |
| 686 | } | 728 | } |
| 687 | 729 | ||
| 730 | /* | ||
| 731 | * A queue for waiters to do rmdir() cgroup. A tasks will sleep when | ||
| 732 | * cgroup->count == 0 && list_empty(&cgroup->children) && subsys has some | ||
| 733 | * reference to css->refcnt. In general, this refcnt is expected to goes down | ||
| 734 | * to zero, soon. | ||
| 735 | * | ||
| 736 | * CGRP_WAIT_ON_RMDIR flag is modified under cgroup's inode->i_mutex; | ||
| 737 | */ | ||
| 738 | DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq); | ||
| 739 | |||
| 740 | static void cgroup_wakeup_rmdir_waiters(const struct cgroup *cgrp) | ||
| 741 | { | ||
| 742 | if (unlikely(test_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) | ||
| 743 | wake_up_all(&cgroup_rmdir_waitq); | ||
| 744 | } | ||
| 745 | |||
| 688 | static int rebind_subsystems(struct cgroupfs_root *root, | 746 | static int rebind_subsystems(struct cgroupfs_root *root, |
| 689 | unsigned long final_bits) | 747 | unsigned long final_bits) |
| 690 | { | 748 | { |
| @@ -857,16 +915,16 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
| 857 | } | 915 | } |
| 858 | 916 | ||
| 859 | ret = rebind_subsystems(root, opts.subsys_bits); | 917 | ret = rebind_subsystems(root, opts.subsys_bits); |
| 918 | if (ret) | ||
| 919 | goto out_unlock; | ||
| 860 | 920 | ||
| 861 | /* (re)populate subsystem files */ | 921 | /* (re)populate subsystem files */ |
| 862 | if (!ret) | 922 | cgroup_populate_dir(cgrp); |
| 863 | cgroup_populate_dir(cgrp); | ||
| 864 | 923 | ||
| 865 | if (opts.release_agent) | 924 | if (opts.release_agent) |
| 866 | strcpy(root->release_agent_path, opts.release_agent); | 925 | strcpy(root->release_agent_path, opts.release_agent); |
| 867 | out_unlock: | 926 | out_unlock: |
| 868 | if (opts.release_agent) | 927 | kfree(opts.release_agent); |
| 869 | kfree(opts.release_agent); | ||
| 870 | mutex_unlock(&cgroup_mutex); | 928 | mutex_unlock(&cgroup_mutex); |
| 871 | mutex_unlock(&cgrp->dentry->d_inode->i_mutex); | 929 | mutex_unlock(&cgrp->dentry->d_inode->i_mutex); |
| 872 | return ret; | 930 | return ret; |
| @@ -969,15 +1027,13 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
| 969 | /* First find the desired set of subsystems */ | 1027 | /* First find the desired set of subsystems */ |
| 970 | ret = parse_cgroupfs_options(data, &opts); | 1028 | ret = parse_cgroupfs_options(data, &opts); |
| 971 | if (ret) { | 1029 | if (ret) { |
| 972 | if (opts.release_agent) | 1030 | kfree(opts.release_agent); |
| 973 | kfree(opts.release_agent); | ||
| 974 | return ret; | 1031 | return ret; |
| 975 | } | 1032 | } |
| 976 | 1033 | ||
| 977 | root = kzalloc(sizeof(*root), GFP_KERNEL); | 1034 | root = kzalloc(sizeof(*root), GFP_KERNEL); |
| 978 | if (!root) { | 1035 | if (!root) { |
| 979 | if (opts.release_agent) | 1036 | kfree(opts.release_agent); |
| 980 | kfree(opts.release_agent); | ||
| 981 | return -ENOMEM; | 1037 | return -ENOMEM; |
| 982 | } | 1038 | } |
| 983 | 1039 | ||
| @@ -1071,7 +1127,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
| 1071 | mutex_unlock(&cgroup_mutex); | 1127 | mutex_unlock(&cgroup_mutex); |
| 1072 | } | 1128 | } |
| 1073 | 1129 | ||
| 1074 | return simple_set_mnt(mnt, sb); | 1130 | simple_set_mnt(mnt, sb); |
| 1131 | return 0; | ||
| 1075 | 1132 | ||
| 1076 | free_cg_links: | 1133 | free_cg_links: |
| 1077 | free_cg_links(&tmp_cg_links); | 1134 | free_cg_links(&tmp_cg_links); |
| @@ -1279,6 +1336,12 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
| 1279 | set_bit(CGRP_RELEASABLE, &oldcgrp->flags); | 1336 | set_bit(CGRP_RELEASABLE, &oldcgrp->flags); |
| 1280 | synchronize_rcu(); | 1337 | synchronize_rcu(); |
| 1281 | put_css_set(cg); | 1338 | put_css_set(cg); |
| 1339 | |||
| 1340 | /* | ||
| 1341 | * wake up rmdir() waiter. the rmdir should fail since the cgroup | ||
| 1342 | * is no longer empty. | ||
| 1343 | */ | ||
| 1344 | cgroup_wakeup_rmdir_waiters(cgrp); | ||
| 1282 | return 0; | 1345 | return 0; |
| 1283 | } | 1346 | } |
| 1284 | 1347 | ||
| @@ -1624,10 +1687,10 @@ static struct inode_operations cgroup_dir_inode_operations = { | |||
| 1624 | .rename = cgroup_rename, | 1687 | .rename = cgroup_rename, |
| 1625 | }; | 1688 | }; |
| 1626 | 1689 | ||
| 1627 | static int cgroup_create_file(struct dentry *dentry, int mode, | 1690 | static int cgroup_create_file(struct dentry *dentry, mode_t mode, |
| 1628 | struct super_block *sb) | 1691 | struct super_block *sb) |
| 1629 | { | 1692 | { |
| 1630 | static struct dentry_operations cgroup_dops = { | 1693 | static const struct dentry_operations cgroup_dops = { |
| 1631 | .d_iput = cgroup_diput, | 1694 | .d_iput = cgroup_diput, |
| 1632 | }; | 1695 | }; |
| 1633 | 1696 | ||
| @@ -1670,7 +1733,7 @@ static int cgroup_create_file(struct dentry *dentry, int mode, | |||
