forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
97978e6d1f
commit
32a8cf235e
@ -1074,7 +1074,8 @@ struct cgroup_sb_opts {
|
||||
*/
|
||||
static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
||||
{
|
||||
char *token, *o = data ?: "all";
|
||||
char *token, *o = data;
|
||||
bool all_ss = false, one_ss = false;
|
||||
unsigned long mask = (unsigned long)-1;
|
||||
int i;
|
||||
bool module_pin_failed = false;
|
||||
@ -1090,24 +1091,27 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
||||
while ((token = strsep(&o, ",")) != NULL) {
|
||||
if (!*token)
|
||||
return -EINVAL;
|
||||
if (!strcmp(token, "all")) {
|
||||
/* Add all non-disabled subsystems */
|
||||
opts->subsys_bits = 0;
|
||||
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
|
||||
struct cgroup_subsys *ss = subsys[i];
|
||||
if (ss == NULL)
|
||||
continue;
|
||||
if (!ss->disabled)
|
||||
opts->subsys_bits |= 1ul << i;
|
||||
}
|
||||
} else if (!strcmp(token, "none")) {
|
||||
if (!strcmp(token, "none")) {
|
||||
/* Explicitly have no subsystems */
|
||||
opts->none = true;
|
||||
} else if (!strcmp(token, "noprefix")) {
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(token, "all")) {
|
||||
/* Mutually exclusive option 'all' + subsystem name */
|
||||
if (one_ss)
|
||||
return -EINVAL;
|
||||
all_ss = true;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(token, "noprefix")) {
|
||||
set_bit(ROOT_NOPREFIX, &opts->flags);
|
||||
} else if (!strcmp(token, "clone_children")) {
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(token, "clone_children")) {
|
||||
opts->clone_children = true;
|
||||
} else if (!strncmp(token, "release_agent=", 14)) {
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(token, "release_agent=", 14)) {
|
||||
/* Specifying two release agents is forbidden */
|
||||
if (opts->release_agent)
|
||||
return -EINVAL;
|
||||
@ -1115,7 +1119,9 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
||||
kstrndup(token + 14, PATH_MAX - 1, GFP_KERNEL);
|
||||
if (!opts->release_agent)
|
||||
return -ENOMEM;
|
||||
} else if (!strncmp(token, "name=", 5)) {
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(token, "name=", 5)) {
|
||||
const char *name = token + 5;
|
||||
/* Can't specify an empty name */
|
||||
if (!strlen(name))
|
||||
@ -1137,20 +1143,44 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
||||
GFP_KERNEL);
|
||||
if (!opts->name)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
struct cgroup_subsys *ss;
|
||||
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
|
||||
ss = subsys[i];
|
||||
if (ss == NULL)
|
||||
continue;
|
||||
if (!strcmp(token, ss->name)) {
|
||||
if (!ss->disabled)
|
||||
set_bit(i, &opts->subsys_bits);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == CGROUP_SUBSYS_COUNT)
|
||||
return -ENOENT;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
|
||||
struct cgroup_subsys *ss = subsys[i];
|
||||
if (ss == NULL)
|
||||
continue;
|
||||
if (strcmp(token, ss->name))
|
||||
continue;
|
||||
if (ss->disabled)
|
||||
continue;
|
||||
|
||||
/* Mutually exclusive option 'all' + subsystem name */
|
||||
if (all_ss)
|
||||
return -EINVAL;
|
||||
set_bit(i, &opts->subsys_bits);
|
||||
one_ss = true;
|
||||
|
||||
break;
|
||||
}
|
||||
if (i == CGROUP_SUBSYS_COUNT)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the 'all' option was specified select all the subsystems,
|
||||
* otherwise 'all, 'none' and a subsystem name options were not
|
||||
* specified, let's default to 'all'
|
||||
*/
|
||||
if (all_ss || (!all_ss && !one_ss && !opts->none)) {
|
||||
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
|
||||
struct cgroup_subsys *ss = subsys[i];
|
||||
if (ss == NULL)
|
||||
continue;
|
||||
if (ss->disabled)
|
||||
continue;
|
||||
set_bit(i, &opts->subsys_bits);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user