diff options
Diffstat (limited to 'kernel/cgroup.c')
| -rw-r--r-- | kernel/cgroup.c | 184 |
1 files changed, 136 insertions, 48 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index f5281aadbcab..03204044622f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include <linux/cgroup.h> | 25 | #include <linux/cgroup.h> |
| 26 | #include <linux/ctype.h> | ||
| 26 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
| 27 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
| 28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| @@ -60,6 +61,8 @@ static struct cgroup_subsys *subsys[] = { | |||
| 60 | #include <linux/cgroup_subsys.h> | 61 | #include <linux/cgroup_subsys.h> |
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 64 | #define MAX_CGROUP_ROOT_NAMELEN 64 | ||
| 65 | |||
| 63 | /* | 66 | /* |
| 64 | * A cgroupfs_root represents the root of a cgroup hierarchy, | 67 | * A cgroupfs_root represents the root of a cgroup hierarchy, |
| 65 | * and may be associated with a superblock to form an active | 68 | * and may be associated with a superblock to form an active |
| @@ -94,6 +97,9 @@ struct cgroupfs_root { | |||
| 94 | 97 | ||
| 95 | /* The path to use for release notifications. */ | 98 | /* The path to use for release notifications. */ |
| 96 | char release_agent_path[PATH_MAX]; | 99 | char release_agent_path[PATH_MAX]; |
| 100 | |||
| 101 | /* The name for this hierarchy - may be empty */ | ||
| 102 | char name[MAX_CGROUP_ROOT_NAMELEN]; | ||
| 97 | }; | 103 | }; |
| 98 | 104 | ||
| 99 | /* | 105 | /* |
| @@ -841,6 +847,8 @@ static int cgroup_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 841 | seq_puts(seq, ",noprefix"); | 847 | seq_puts(seq, ",noprefix"); |
| 842 | if (strlen(root->release_agent_path)) | 848 | if (strlen(root->release_agent_path)) |
| 843 | seq_printf(seq, ",release_agent=%s", root->release_agent_path); | 849 | seq_printf(seq, ",release_agent=%s", root->release_agent_path); |
| 850 | if (strlen(root->name)) | ||
| 851 | seq_printf(seq, ",name=%s", root->name); | ||
| 844 | mutex_unlock(&cgroup_mutex); | 852 | mutex_unlock(&cgroup_mutex); |
| 845 | return 0; | 853 | return 0; |
| 846 | } | 854 | } |
| @@ -849,6 +857,9 @@ struct cgroup_sb_opts { | |||
| 849 | unsigned long subsys_bits; | 857 | unsigned long subsys_bits; |
| 850 | unsigned long flags; | 858 | unsigned long flags; |
| 851 | char *release_agent; | 859 | char *release_agent; |
| 860 | char *name; | ||
| 861 | |||
| 862 | struct cgroupfs_root *new_root; | ||
| 852 | }; | 863 | }; |
| 853 | 864 | ||
| 854 | /* Convert a hierarchy specifier into a bitmask of subsystems and | 865 | /* Convert a hierarchy specifier into a bitmask of subsystems and |
| @@ -863,9 +874,7 @@ static int parse_cgroupfs_options(char *data, | |||
| 863 | mask = ~(1UL << cpuset_subsys_id); | 874 | mask = ~(1UL << cpuset_subsys_id); |
| 864 | #endif | 875 | #endif |
| 865 | 876 | ||
| 866 | opts->subsys_bits = 0; | 877 | memset(opts, 0, sizeof(*opts)); |
| 867 | opts->flags = 0; | ||
| 868 | opts->release_agent = NULL; | ||
| 869 | 878 | ||
| 870 | while ((token = strsep(&o, ",")) != NULL) { | 879 | while ((token = strsep(&o, ",")) != NULL) { |
| 871 | if (!*token) | 880 | if (!*token) |
| @@ -885,11 +894,33 @@ static int parse_cgroupfs_options(char *data, | |||
| 885 | /* Specifying two release agents is forbidden */ | 894 | /* Specifying two release agents is forbidden */ |
| 886 | if (opts->release_agent) | 895 | if (opts->release_agent) |
| 887 | return -EINVAL; | 896 | return -EINVAL; |
| 888 | opts->release_agent = kzalloc(PATH_MAX, GFP_KERNEL); | 897 | opts->release_agent = |
| 898 | kstrndup(token + 14, PATH_MAX, GFP_KERNEL); | ||
| 889 | if (!opts->release_agent) | 899 | if (!opts->release_agent) |
| 890 | return -ENOMEM; | 900 | return -ENOMEM; |
| 891 | strncpy(opts->release_agent, token + 14, PATH_MAX - 1); | 901 | } else if (!strncmp(token, "name=", 5)) { |
| 892 | opts->release_agent[PATH_MAX - 1] = 0; | 902 | int i; |
| 903 | const char *name = token + 5; | ||
| 904 | /* Can't specify an empty name */ | ||
| 905 | if (!strlen(name)) | ||
| 906 | return -EINVAL; | ||
| 907 | /* Must match [\w.-]+ */ | ||
| 908 | for (i = 0; i < strlen(name); i++) { | ||
| 909 | char c = name[i]; | ||
| 910 | if (isalnum(c)) | ||
| 911 | continue; | ||
| 912 | if ((c == '.') || (c == '-') || (c == '_')) | ||
| 913 | continue; | ||
| 914 | return -EINVAL; | ||
| 915 | } | ||
| 916 | /* Specifying two names is forbidden */ | ||
| 917 | if (opts->name) | ||
| 918 | return -EINVAL; | ||
| 919 | opts->name = kstrndup(name, | ||
| 920 | MAX_CGROUP_ROOT_NAMELEN, | ||
| 921 | GFP_KERNEL); | ||
| 922 | if (!opts->name) | ||
| 923 | return -ENOMEM; | ||
| 893 | } else { | 924 | } else { |
| 894 | struct cgroup_subsys *ss; | 925 | struct cgroup_subsys *ss; |
| 895 | int i; | 926 | int i; |
| @@ -916,7 +947,7 @@ static int parse_cgroupfs_options(char *data, | |||
| 916 | return -EINVAL; | 947 | return -EINVAL; |
| 917 | 948 | ||
| 918 | /* We can't have an empty hierarchy */ | 949 | /* We can't have an empty hierarchy */ |
| 919 | if (!opts->subsys_bits) | 950 | if (!opts->subsys_bits && !opts->name) |
| 920 | return -EINVAL; | 951 | return -EINVAL; |
| 921 | 952 | ||
| 922 | return 0; | 953 | return 0; |
| @@ -944,6 +975,12 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
| 944 | goto out_unlock; | 975 | goto out_unlock; |
| 945 | } | 976 | } |
| 946 | 977 | ||
| 978 | /* Don't allow name to change at remount */ | ||
| 979 | if (opts.name && strcmp(opts.name, root->name)) { | ||
| 980 | ret = -EINVAL; | ||
| 981 | goto out_unlock; | ||
| 982 | } | ||
| 983 | |||
| 947 | ret = rebind_subsystems(root, opts.subsys_bits); | 984 | ret = rebind_subsystems(root, opts.subsys_bits); |
| 948 | if (ret) | 985 | if (ret) |
| 949 | goto out_unlock; | 986 | goto out_unlock; |
| @@ -955,6 +992,7 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
| 955 | strcpy(root->release_agent_path, opts.release_agent); | 992 | strcpy(root->release_agent_path, opts.release_agent); |
| 956 | out_unlock: | 993 | out_unlock: |
| 957 | kfree(opts.release_agent); | 994 | kfree(opts.release_agent); |
| 995 | kfree(opts.name); | ||
| 958 | mutex_unlock(&cgroup_mutex); | 996 | mutex_unlock(&cgroup_mutex); |
| 959 | mutex_unlock(&cgrp->dentry->d_inode->i_mutex); | 997 | mutex_unlock(&cgrp->dentry->d_inode->i_mutex); |
| 960 | unlock_kernel(); | 998 | unlock_kernel(); |
| @@ -977,6 +1015,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
| 977 | INIT_LIST_HEAD(&cgrp->pids_list); | 1015 | INIT_LIST_HEAD(&cgrp->pids_list); |
| 978 | init_rwsem(&cgrp->pids_mutex); | 1016 | init_rwsem(&cgrp->pids_mutex); |
| 979 | } | 1017 | } |
| 1018 | |||
| 980 | static void init_cgroup_root(struct cgroupfs_root *root) | 1019 | static void init_cgroup_root(struct cgroupfs_root *root) |
| 981 | { | 1020 | { |
| 982 | struct cgroup *cgrp = &root->top_cgroup; | 1021 | struct cgroup *cgrp = &root->top_cgroup; |
| @@ -990,31 +1029,59 @@ static void init_cgroup_root(struct cgroupfs_root *root) | |||
| 990 | 1029 | ||
| 991 | static int cgroup_test_super(struct super_block *sb, void *data) | 1030 | static int cgroup_test_super(struct super_block *sb, void *data) |
| 992 | { | 1031 | { |
| 993 | struct cgroupfs_root *new = data; | 1032 | struct cgroup_sb_opts *opts = data; |
| 994 | struct cgroupfs_root *root = sb->s_fs_info; | 1033 | struct cgroupfs_root *root = sb->s_fs_info; |
| 995 | 1034 | ||
| 996 | /* First check subsystems */ | 1035 | /* If we asked for a name then it must match */ |
| 997 | if (new->subsys_bits != root->subsys_bits) | 1036 | if (opts->name && strcmp(opts->name, root->name)) |
| 998 | return 0; | 1037 | return 0; |
| 999 | 1038 | ||
| 1000 | /* Next check flags */ | 1039 | /* If we asked for subsystems then they must match */ |
| 1001 | if (new->flags != root->flags) | 1040 | if (opts->subsys_bits && (opts->subsys_bits != root->subsys_bits)) |
| 1002 | return 0; | 1041 | return 0; |
| 1003 | 1042 | ||
| 1004 | return 1; | 1043 | return 1; |
| 1005 | } | 1044 | } |
| 1006 | 1045 | ||
| 1046 | static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts) | ||
| 1047 | { | ||
| 1048 | struct cgroupfs_root *root; | ||
| 1049 | |||
| 1050 | /* Empty hierarchies aren't supported */ | ||
| 1051 | if (!opts->subsys_bits) | ||
| 1052 | return NULL; | ||
| 1053 | |||
| 1054 | root = kzalloc(sizeof(*root), GFP_KERNEL); | ||
| 1055 | if (!root) | ||
| 1056 | return ERR_PTR(-ENOMEM); | ||
| 1057 | |||
| 1058 | init_cgroup_root(root); | ||
| 1059 | root->subsys_bits = opts->subsys_bits; | ||
| 1060 | root->flags = opts->flags; | ||
| 1061 | if (opts->release_agent) | ||
| 1062 | strcpy(root->release_agent_path, opts->release_agent); | ||
| 1063 | if (opts->name) | ||
| 1064 | strcpy(root->name, opts->name); | ||
| 1065 | return root; | ||
| 1066 | } | ||
| 1067 | |||
| 1007 | static int cgroup_set_super(struct super_block *sb, void *data) | 1068 | static int cgroup_set_super(struct super_block *sb, void *data) |
| 1008 | { | 1069 | { |
| 1009 | int ret; | 1070 | int ret; |
| 1010 | struct cgroupfs_root *root = data; | 1071 | struct cgroup_sb_opts *opts = data; |
| 1072 | |||
| 1073 | /* If we don't have a new root, we can't set up a new sb */ | ||
| 1074 | if (!opts->new_root) | ||
| 1075 | return -EINVAL; | ||
| 1076 | |||
| 1077 | BUG_ON(!opts->subsys_bits); | ||
| 1011 | 1078 | ||
| 1012 | ret = set_anon_super(sb, NULL); | 1079 | ret = set_anon_super(sb, NULL); |
| 1013 | if (ret) | 1080 | if (ret) |
| 1014 | return ret; | 1081 | return ret; |
| 1015 | 1082 | ||
| 1016 | sb->s_fs_info = root; | 1083 | sb->s_fs_info = opts->new_root; |
| 1017 | root->sb = sb; | 1084 | opts->new_root->sb = sb; |
| 1018 | 1085 | ||
| 1019 | sb->s_blocksize = PAGE_CACHE_SIZE; | 1086 | sb->s_blocksize = PAGE_CACHE_SIZE; |
| 1020 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 1087 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
| @@ -1051,48 +1118,43 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
| 1051 | void *data, struct vfsmount *mnt) | 1118 | void *data, struct vfsmount *mnt) |
| 1052 | { | 1119 | { |
| 1053 | struct cgroup_sb_opts opts; | 1120 | struct cgroup_sb_opts opts; |
| 1121 | struct cgroupfs_root *root; | ||
| 1054 | int ret = 0; | 1122 | int ret = 0; |
| 1055 | struct super_block *sb; | 1123 | struct super_block *sb; |
| 1056 | struct cgroupfs_root *root; | 1124 | struct cgroupfs_root *new_root; |
| 1057 | struct list_head tmp_cg_links; | ||
| 1058 | 1125 | ||
| 1059 | /* First find the desired set of subsystems */ | 1126 | /* First find the desired set of subsystems */ |
| 1060 | ret = parse_cgroupfs_options(data, &opts); | 1127 | ret = parse_cgroupfs_options(data, &opts); |
| 1061 | if (ret) { | 1128 | if (ret) |
| 1062 | kfree(opts.release_agent); | 1129 | goto out_err; |
| 1063 | return ret; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | root = kzalloc(sizeof(*root), GFP_KERNEL); | ||
| 1067 | if (!root) { | ||
| 1068 | kfree(opts.release_agent); | ||
| 1069 | return -ENOMEM; | ||
| 1070 | } | ||
| 1071 | 1130 | ||
| 1072 | init_cgroup_root(root); | 1131 | /* |
| 1073 | root->subsys_bits = opts.subsys_bits; | 1132 | * Allocate a new cgroup root. We may not need it if we're |
| 1074 | root->flags = opts.flags; | 1133 | * reusing an existing hierarchy. |
| 1075 | if (opts.release_agent) { | 1134 | */ |
| 1076 | strcpy(root->release_agent_path, opts.release_agent); | 1135 | new_root = cgroup_root_from_opts(&opts); |
| 1077 | kfree(opts.release_agent); | 1136 | if (IS_ERR(new_root)) { |
| 1137 | ret = PTR_ERR(new_root); | ||
| 1138 | goto out_err; | ||
| 1078 | } | 1139 | } |
| 1140 | opts.new_root = new_root; | ||
| 1079 | 1141 | ||
| 1080 | sb = sget(fs_type, cgroup_test_super, cgroup_set_super, root); | 1142 | /* Locate an existing or new sb for this hierarchy */ |
| 1081 | 1143 | sb = sget(fs_type, cgroup_test_super, cgroup_set_super, &opts); | |
| 1082 | if (IS_ERR(sb)) { | 1144 | if (IS_ERR(sb)) { |
| 1083 | kfree(root); | 1145 | ret = PTR_ERR(sb); |
| 1084 | return PTR_ERR(sb); | 1146 | kfree(opts.new_root); |
| 1147 | goto out_err; | ||
| 1085 | } | 1148 | } |
| 1086 | 1149 | ||
| 1087 | if (sb->s_fs_info != root) { | 1150 | root = sb->s_fs_info; |
| 1088 | /* Reusing an existing superblock */ | 1151 | BUG_ON(!root); |
| 1089 | BUG_ON(sb->s_root == NULL); | 1152 | if (root == opts.new_root) { |
| 1090 | kfree(root); | 1153 | /* We used the new root structure, so this is a new hierarchy */ |
| 1091 | root = NULL; | 1154 | struct list_head tmp_cg_links; |
| 1092 | } else { | ||
| 1093 | /* New superblock */ | ||
| 1094 | struct cgroup *root_cgrp = &root->top_cgroup; | 1155 | struct cgroup *root_cgrp = &root->top_cgroup; |
| 1095 | struct inode *inode; | 1156 | struct inode *inode; |
| 1157 | struct cgroupfs_root *existing_root; | ||
| 1096 | int i; | 1158 | int i; |
| 1097 | 1159 | ||
| 1098 | BUG_ON(sb->s_root != NULL); | 1160 | BUG_ON(sb->s_root != NULL); |
| @@ -1105,6 +1167,18 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
| 1105 | mutex_lock(&inode->i_mutex); | 1167 | mutex_lock(&inode->i_mutex); |
| 1106 | mutex_lock(&cgroup_mutex); | 1168 | mutex_lock(&cgroup_mutex); |
| 1107 | 1169 | ||
| 1170 | if (strlen(root->name)) { | ||
| 1171 | /* Check for name clashes with existing mounts */ | ||
| 1172 | for_each_active_root(existing_root) { | ||
| 1173 | if (!strcmp(existing_root->name, root->name)) { | ||
| 1174 | ret = -EBUSY; | ||
| 1175 | mutex_unlock(&cgroup_mutex); | ||
| 1176 | mutex_unlock(&inode->i_mutex); | ||
| 1177 | goto drop_new_super; | ||
| 1178 | } | ||
| 1179 | } | ||
| 1180 | } | ||
| 1181 | |||
| 1108 | /* | 1182 | /* |
| 1109 | * We're accessing css_set_count without locking | 1183 | * We're accessing css_set_count without locking |
| 1110 | * css_set_lock here, but that's OK - it can only be | 1184 | * css_set_lock here, but that's OK - it can only be |
| @@ -1123,7 +1197,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
| 1123 | if (ret == -EBUSY) { | 1197 | if (ret == -EBUSY) { |
| 1124 | mutex_unlock(&cgroup_mutex); | 1198 | mutex_unlock(&cgroup_mutex); |
| 1125 | mutex_unlock(&inode->i_mutex); | 1199 | mutex_unlock(&inode->i_mutex); |
| 1126 | goto free_cg_links; | 1200 | free_cg_links(&tmp_cg_links); |
| 1201 | goto drop_new_super; | ||
| 1127 | } | 1202 | } |
| 1128 | 1203 | ||
| 1129 | /* EBUSY should be the only error here */ | 1204 | /* EBUSY should be the only error here */ |
| @@ -1157,15 +1232,25 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
| 1157 | cgroup_populate_dir(root_cgrp); | 1232 | cgroup_populate_dir(root_cgrp); |
| 1158 | mutex_unlock(&cgroup_mutex); | 1233 | mutex_unlock(&cgroup_mutex); |
| 1159 | mutex_unlock(&inode->i_mutex); | 1234 | mutex_unlock(&inode->i_mutex); |
| 1235 | } else { | ||
| 1236 | /* | ||
| 1237 | * We re-used an existing hierarchy - the new root (if | ||
| 1238 | * any) is not needed | ||
| 1239 | */ | ||
| 1240 | kfree(opts.new_root); | ||
| 1160 | } | 1241 | } |
| 1161 | 1242 | ||
| 1162 | simple_set_mnt(mnt, sb); | 1243 | simple_set_mnt(mnt, sb); |
| 1244 | kfree(opts.release_agent); | ||
| 1245 | kfree(opts.name); | ||
| 1163 | return 0; | 1246 | return 0; |
| 1164 | 1247 | ||
| 1165 | free_cg_links: | ||
| 1166 | free_cg_links(&tmp_cg_links); | ||
| 1167 | drop_new_super: | 1248 | drop_new_super: |
| 1168 | deactivate_locked_super(sb); | 1249 | deactivate_locked_super(sb); |
| 1250 | out_err: | ||
| 1251 | kfree(opts.release_agent); | ||
| 1252 | kfree(opts.name); | ||
| 1253 | |||
| 1169 | return ret; | 1254 | return ret; |
| 1170 | } | 1255 | } |
| 1171 | 1256 | ||
| @@ -2992,6 +3077,9 @@ static int proc_cgroup_show(struct seq_file *m, void *v) | |||
| 2992 | seq_printf(m, "%lu:", root->subsys_bits); | 3077 | seq_printf(m, "%lu:", root->subsys_bits); |
| 2993 | for_each_subsys(root, ss) | 3078 | for_each_subsys(root, ss) |
| 2994 | seq_printf(m, "%s%s", count++ ? "," : "", ss->name); | 3079 | seq_printf(m, "%s%s", count++ ? "," : "", ss->name); |
| 3080 | if (strlen(root->name)) | ||
| 3081 | seq_printf(m, "%sname=%s", count ? "," : "", | ||
| 3082 | root->name); | ||
| 2995 | seq_putc(m, ':'); | 3083 | seq_putc(m, ':'); |
| 2996 | get_first_subsys(&root->top_cgroup, NULL, &subsys_id); | 3084 | get_first_subsys(&root->top_cgroup, NULL, &subsys_id); |
| 2997 | cgrp = task_cgroup(tsk, subsys_id); | 3085 | cgrp = task_cgroup(tsk, subsys_id); |
