aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@free.fr>2010-10-27 18:33:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-27 21:03:09 -0400
commit32a8cf235e2f192eb002755076994525cdbaa35a (patch)
treea4d849c31703d18365e063a4cc7627bfd13ca253 /kernel/cgroup.c
parent97978e6d1f2da0073416870410459694fbdbfd9b (diff)
cgroup: make the mount options parsing more accurate
Current behavior: ================= (1) When we mount a cgroup, we can specify the 'all' option which means to enable all the cgroup subsystems. This is the default option when no option is specified. (2) If we want to mount a cgroup with a subset of the supported cgroup subsystems, we have to specify a subsystems name list for the mount option. (3) If we specify another option like 'noprefix' or 'release_agent', the actual code wants the 'all' or a subsystem name option specified also. Not critical but a bit not friendly as we should assume (1) in this case. (4) Logically, the 'all' option is mutually exclusive with a subsystem name, but this is not detected. In other words: succeed : mount -t cgroup -o all,freezer cgroup /cgroup => is it 'all' or 'freezer' ? fails : mount -t cgroup -o noprefix cgroup /cgroup => succeed if we do '-o noprefix,all' The following patches consolidate a bit the mount options check. New behavior: ============= (1) untouched (2) untouched (3) the 'all' option will be by default when specifying other than a subsystem name option (4) raises an error In other words: fails : mount -t cgroup -o all,freezer cgroup /cgroup succeed : mount -t cgroup -o noprefix cgroup /cgroup For the sake of lisibility, the if ... then ... else ... if ... indentation when parsing the options has been changed to: if ... then ... continue fi Signed-off-by: Daniel Lezcano <daniel.lezcano@free.fr> Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com> Reviewed-by: Li Zefan <lizf@cn.fujitsu.com> Reviewed-by: Paul Menage <menage@google.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Jamal Hadi Salim <hadi@cyberus.ca> Cc: Matt Helsley <matthltc@us.ibm.com> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c90
1 files changed, 60 insertions, 30 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4b218a46ddd3..3e6517e51fd3 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1074,7 +1074,8 @@ struct cgroup_sb_opts {
1074 */ 1074 */
1075static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) 1075static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
1076{ 1076{
1077 char *token, *o = data ?: "all"; 1077 char *token, *o = data;
1078 bool all_ss = false, one_ss = false;
1078 unsigned long mask = (unsigned long)-1; 1079 unsigned long mask = (unsigned long)-1;
1079 int i; 1080 int i;
1080 bool module_pin_failed = false; 1081 bool module_pin_failed = false;
@@ -1090,24 +1091,27 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
1090 while ((token = strsep(&o, ",")) != NULL) { 1091 while ((token = strsep(&o, ",")) != NULL) {
1091 if (!*token) 1092 if (!*token)
1092 return -EINVAL; 1093 return -EINVAL;
1093 if (!strcmp(token, "all")) { 1094 if (!strcmp(token, "none")) {
1094 /* Add all non-disabled subsystems */
1095 opts->subsys_bits = 0;
1096 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
1097 struct cgroup_subsys *ss = subsys[i];
1098 if (ss == NULL)
1099 continue;
1100 if (!ss->disabled)
1101 opts->subsys_bits |= 1ul << i;
1102 }
1103 } else if (!strcmp(token, "none")) {
1104 /* Explicitly have no subsystems */ 1095 /* Explicitly have no subsystems */
1105 opts->none = true; 1096 opts->none = true;
1106 } else if (!strcmp(token, "noprefix")) { 1097 continue;
1098 }
1099 if (!strcmp(token, "all")) {
1100 /* Mutually exclusive option 'all' + subsystem name */
1101 if (one_ss)
1102 return -EINVAL;
1103 all_ss = true;
1104 continue;
1105 }
1106 if (!strcmp(token, "noprefix")) {
1107 set_bit(ROOT_NOPREFIX, &opts->flags); 1107 set_bit(ROOT_NOPREFIX, &opts->flags);
1108 } else if (!strcmp(token, "clone_children")) { 1108 continue;
1109 }
1110 if (!strcmp(token, "clone_children")) {
1109 opts->clone_children = true; 1111 opts->clone_children = true;
1110 } else if (!strncmp(token, "release_agent=", 14)) { 1112 continue;
1113 }
1114 if (!strncmp(token, "release_agent=", 14)) {
1111 /* Specifying two release agents is forbidden */ 1115 /* Specifying two release agents is forbidden */
1112 if (opts->release_agent) 1116 if (opts->release_agent)
1113 return -EINVAL; 1117 return -EINVAL;
@@ -1115,7 +1119,9 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
1115 kstrndup(token + 14, PATH_MAX - 1, GFP_KERNEL); 1119 kstrndup(token + 14, PATH_MAX - 1, GFP_KERNEL);
1116 if (!opts->release_agent) 1120 if (!opts->release_agent)
1117 return -ENOMEM; 1121 return -ENOMEM;
1118 } else if (!strncmp(token, "name=", 5)) { 1122 continue;
1123 }
1124 if (!strncmp(token, "name=", 5)) {
1119 const char *name = token + 5; 1125 const char *name = token + 5;
1120 /* Can't specify an empty name */ 1126 /* Can't specify an empty name */
1121 if (!strlen(name)) 1127 if (!strlen(name))
@@ -1137,20 +1143,44 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
1137 GFP_KERNEL); 1143 GFP_KERNEL);
1138 if (!opts->name) 1144 if (!opts->name)
1139 return -ENOMEM; 1145 return -ENOMEM;
1140 } else { 1146
1141 struct cgroup_subsys *ss; 1147 continue;
1142 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { 1148 }
1143 ss = subsys[i]; 1149
1144 if (ss == NULL) 1150 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
1145 continue; 1151 struct cgroup_subsys *ss = subsys[i];
1146 if (!strcmp(token, ss->name)) { 1152 if (ss == NULL)
1147 if (!ss->disabled) 1153 continue;
1148 set_bit(i, &opts->subsys_bits); 1154 if (strcmp(token, ss->name))
1149 break; 1155 continue;
1150 } 1156 if (ss->disabled)
1151 } 1157 continue;
1152 if (i == CGROUP_SUBSYS_COUNT) 1158
1153 return -ENOENT; 1159 /* Mutually exclusive option 'all' + subsystem name */
1160 if (all_ss)
1161 return -EINVAL;
1162 set_bit(i, &opts->subsys_bits);
1163 one_ss = true;
1164
1165 break;
1166 }
1167 if (i == CGROUP_SUBSYS_COUNT)
1168 return -ENOENT;
1169 }
1170
1171 /*
1172 * If the 'all' option was specified select all the subsystems,
1173 * otherwise 'all, 'none' and a subsystem name options were not
1174 * specified, let's default to 'all'
1175 */
1176 if (all_ss || (!all_ss && !one_ss && !opts->none)) {
1177 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
1178 struct cgroup_subsys *ss = subsys[i];
1179 if (ss == NULL)
1180 continue;
1181 if (ss->disabled)
1182 continue;
1183 set_bit(i, &opts->subsys_bits);
1154 } 1184 }
1155 } 1185 }
1156 1186