cgroups: handle offline cpus in v1 hierarchy

Handle offline cpus in v1 hierarchy. In addition to isolated cpus we also need to account for offline cpus when our ancestor cgroup is the root cgroup and we have not been initialized yet. Closes #2953. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 8a545679
...@@ -378,16 +378,18 @@ static ssize_t get_max_cpus(char *cpulist) ...@@ -378,16 +378,18 @@ static ssize_t get_max_cpus(char *cpulist)
} }
#define __ISOL_CPUS "/sys/devices/system/cpu/isolated" #define __ISOL_CPUS "/sys/devices/system/cpu/isolated"
#define __OFFLINE_CPUS "/sys/devices/system/cpu/offline"
static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized) static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
{ {
__do_free char *cpulist = NULL, *fpath = NULL, *isolcpus = NULL, __do_free char *cpulist = NULL, *fpath = NULL, *isolcpus = NULL,
*posscpus = NULL; *offlinecpus = NULL, *posscpus = NULL;
__do_free uint32_t *isolmask = NULL, *possmask = NULL; __do_free uint32_t *isolmask = NULL, *offlinemask = NULL,
*possmask = NULL;
int ret; int ret;
ssize_t i; ssize_t i;
char oldv; char oldv;
char *lastslash; char *lastslash;
ssize_t maxisol = 0, maxposs = 0; ssize_t maxisol = 0, maxoffline = 0, maxposs = 0;
bool bret = false, flipped_bit = false; bool bret = false, flipped_bit = false;
lastslash = strrchr(path, '/'); lastslash = strrchr(path, '/');
...@@ -409,54 +411,50 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized) ...@@ -409,54 +411,50 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
if (maxposs < 0 || maxposs >= INT_MAX - 1) if (maxposs < 0 || maxposs >= INT_MAX - 1)
return false; return false;
if (!file_exists(__ISOL_CPUS)) { if (file_exists(__ISOL_CPUS)) {
/* This system doesn't expose isolated cpus. */ isolcpus = read_file(__ISOL_CPUS);
DEBUG("The path \""__ISOL_CPUS"\" to read isolated cpus from does not exist"); if (!isolcpus) {
/* No isolated cpus but we weren't already initialized by SYSERROR("Failed to read file \"%s\"", __ISOL_CPUS);
* someone. We should simply copy the parents cpuset.cpus return false;
* values.
*/
if (!am_initialized) {
DEBUG("Copying cpu settings of parent cgroup");
cpulist = posscpus;
goto copy_parent;
} }
/* No isolated cpus but we were already initialized by someone.
* Nothing more to do for us.
*/
return true;
}
isolcpus = read_file(__ISOL_CPUS); if (isdigit(isolcpus[0])) {
if (!isolcpus) { /* Get maximum number of cpus found in isolated cpuset. */
SYSERROR("Failed to read file \""__ISOL_CPUS"\""); maxisol = get_max_cpus(isolcpus);
return false; if (maxisol < 0 || maxisol >= INT_MAX - 1)
} return false;
if (!isdigit(isolcpus[0])) {
TRACE("No isolated cpus detected");
/* No isolated cpus but we weren't already initialized by
* someone. We should simply copy the parents cpuset.cpus
* values.
*/
if (!am_initialized) {
DEBUG("Copying cpu settings of parent cgroup");
cpulist = posscpus;
goto copy_parent;
} }
/* No isolated cpus but we were already initialized by someone.
* Nothing more to do for us. if (maxposs < maxisol)
*/ maxposs = maxisol;
return true; maxposs++;
} else {
TRACE("The path \""__ISOL_CPUS"\" to read isolated cpus from does not exist");
} }
/* Get maximum number of cpus found in isolated cpuset. */ if (file_exists(__OFFLINE_CPUS)) {
maxisol = get_max_cpus(isolcpus); offlinecpus = read_file(__OFFLINE_CPUS);
if (maxisol < 0 || maxisol >= INT_MAX - 1) if (!offlinecpus) {
return false; SYSERROR("Failed to read file \"%s\"", __OFFLINE_CPUS);
return false;
}
if (maxposs < maxisol) if (isdigit(offlinecpus[0])) {
maxposs = maxisol; /* Get maximum number of cpus found in offline cpuset. */
maxposs++; maxoffline = get_max_cpus(offlinecpus);
if (maxoffline < 0 || maxoffline >= INT_MAX - 1)
return false;
}
if (maxposs < maxoffline)
maxposs = maxoffline;
maxposs++;
} else {
TRACE("The path \""__OFFLINE_CPUS"\" to read offline cpus from does not exist");
}
if ((maxisol == 0) && (maxoffline == 0))
goto copy_parent;
possmask = lxc_cpumask(posscpus, maxposs); possmask = lxc_cpumask(posscpus, maxposs);
if (!possmask) { if (!possmask) {
...@@ -464,14 +462,26 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized) ...@@ -464,14 +462,26 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
return false; return false;
} }
isolmask = lxc_cpumask(isolcpus, maxposs); if (maxisol > 0) {
if (!isolmask) { isolmask = lxc_cpumask(isolcpus, maxposs);
ERROR("Failed to create cpumask for isolated cpus"); if (!isolmask) {
return false; ERROR("Failed to create cpumask for isolated cpus");
return false;
}
}
if (maxoffline > 0) {
offlinemask = lxc_cpumask(offlinecpus, maxposs);
if (!offlinemask) {
ERROR("Failed to create cpumask for offline cpus");
return false;
}
} }
for (i = 0; i <= maxposs; i++) { for (i = 0; i <= maxposs; i++) {
if (!is_set(i, isolmask) || !is_set(i, possmask)) if ((isolmask && !is_set(i, isolmask)) ||
(offlinemask && !is_set(i, offlinemask)) ||
!is_set(i, possmask))
continue; continue;
flipped_bit = true; flipped_bit = true;
...@@ -479,10 +489,10 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized) ...@@ -479,10 +489,10 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
} }
if (!flipped_bit) { if (!flipped_bit) {
DEBUG("No isolated cpus present in cpuset"); DEBUG("No isolated or offline cpus present in cpuset");
return true; return true;
} }
DEBUG("Removed isolated cpus from cpuset"); DEBUG("Removed isolated or offline cpus from cpuset");
cpulist = lxc_cpumask_to_cpulist(possmask, maxposs); cpulist = lxc_cpumask_to_cpulist(possmask, maxposs);
if (!cpulist) { if (!cpulist) {
...@@ -491,14 +501,19 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized) ...@@ -491,14 +501,19 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
} }
copy_parent: copy_parent:
*lastslash = oldv; if (!am_initialized) {
fpath = must_make_path(path, "cpuset.cpus", NULL); *lastslash = oldv;
ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false, 0666); fpath = must_make_path(path, "cpuset.cpus", NULL);
if (cpulist == posscpus) ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false,
cpulist = NULL; 0666);
if (ret < 0) { if (cpulist == posscpus)
SYSERROR("Failed to write cpu list to \"%s\"", fpath); cpulist = NULL;
return false; if (ret < 0) {
SYSERROR("Failed to write cpu list to \"%s\"", fpath);
return false;
}
TRACE("Copied cpu settings of parent cgroup");
} }
return true; return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment