diff options
author | Daniel Lezcano <daniel.lezcano@free.fr> | 2010-10-27 18:33:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-27 21:03:09 -0400 |
commit | 32a8cf235e2f192eb002755076994525cdbaa35a (patch) | |
tree | a4d849c31703d18365e063a4cc7627bfd13ca253 /kernel | |
parent | 97978e6d1f2da0073416870410459694fbdbfd9b (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')
-rw-r--r-- | kernel/cgroup.c | 90 |
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 | */ |
1075 | static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) | 1075 | static 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 | ||