Skip to content

Commit

Permalink
cgroups: handle offline cpus in v1 hierarchy
Browse files Browse the repository at this point in the history
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: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Jun 13, 2019
1 parent 8a54567 commit ada49c3
Showing 1 changed file with 75 additions and 60 deletions.
135 changes: 75 additions & 60 deletions src/lxc/cgroups/cgfsng.c
Expand Up @@ -378,16 +378,18 @@ static ssize_t get_max_cpus(char *cpulist)
}

#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)
{
__do_free char *cpulist = NULL, *fpath = NULL, *isolcpus = NULL,
*posscpus = NULL;
__do_free uint32_t *isolmask = NULL, *possmask = NULL;
*offlinecpus = NULL, *posscpus = NULL;
__do_free uint32_t *isolmask = NULL, *offlinemask = NULL,
*possmask = NULL;
int ret;
ssize_t i;
char oldv;
char *lastslash;
ssize_t maxisol = 0, maxposs = 0;
ssize_t maxisol = 0, maxoffline = 0, maxposs = 0;
bool bret = false, flipped_bit = false;

lastslash = strrchr(path, '/');
Expand All @@ -409,80 +411,88 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
if (maxposs < 0 || maxposs >= INT_MAX - 1)
return false;

if (!file_exists(__ISOL_CPUS)) {
/* This system doesn't expose isolated cpus. */
DEBUG("The path \""__ISOL_CPUS"\" to read isolated cpus from does not exist");
/* 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;
if (file_exists(__ISOL_CPUS)) {
isolcpus = read_file(__ISOL_CPUS);
if (!isolcpus) {
SYSERROR("Failed to read file \"%s\"", __ISOL_CPUS);
return false;
}
/* No isolated cpus but we were already initialized by someone.
* Nothing more to do for us.
*/
return true;
}

isolcpus = read_file(__ISOL_CPUS);
if (!isolcpus) {
SYSERROR("Failed to read file \""__ISOL_CPUS"\"");
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;
if (isdigit(isolcpus[0])) {
/* Get maximum number of cpus found in isolated cpuset. */
maxisol = get_max_cpus(isolcpus);
if (maxisol < 0 || maxisol >= INT_MAX - 1)
return false;
}
/* No isolated cpus but we were already initialized by someone.
* Nothing more to do for us.
*/
return true;

if (maxposs < maxisol)
maxposs = maxisol;
maxposs++;
} else {
TRACE("The path \""__ISOL_CPUS"\" to read isolated cpus from does not exist");
}

/* Get maximum number of cpus found in isolated cpuset. */
maxisol = get_max_cpus(isolcpus);
if (maxisol < 0 || maxisol >= INT_MAX - 1)
return false;
if (file_exists(__OFFLINE_CPUS)) {
offlinecpus = read_file(__OFFLINE_CPUS);
if (!offlinecpus) {
SYSERROR("Failed to read file \"%s\"", __OFFLINE_CPUS);
return false;
}

if (maxposs < maxisol)
maxposs = maxisol;
maxposs++;
if (isdigit(offlinecpus[0])) {
/* Get maximum number of cpus found in offline cpuset. */
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);
if (!possmask) {
ERROR("Failed to create cpumask for possible cpus");
return false;
}

isolmask = lxc_cpumask(isolcpus, maxposs);
if (!isolmask) {
ERROR("Failed to create cpumask for isolated cpus");
return false;
if (maxisol > 0) {
isolmask = lxc_cpumask(isolcpus, maxposs);
if (!isolmask) {
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++) {
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;

flipped_bit = true;
clear_bit(i, possmask);
}

if (!flipped_bit) {
DEBUG("No isolated cpus present in cpuset");
DEBUG("No isolated or offline cpus present in cpuset");
return true;
}
DEBUG("Removed isolated cpus from cpuset");
DEBUG("Removed isolated or offline cpus from cpuset");

cpulist = lxc_cpumask_to_cpulist(possmask, maxposs);
if (!cpulist) {
Expand All @@ -491,14 +501,19 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
}

copy_parent:
*lastslash = oldv;
fpath = must_make_path(path, "cpuset.cpus", NULL);
ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false, 0666);
if (cpulist == posscpus)
cpulist = NULL;
if (ret < 0) {
SYSERROR("Failed to write cpu list to \"%s\"", fpath);
return false;
if (!am_initialized) {
*lastslash = oldv;
fpath = must_make_path(path, "cpuset.cpus", NULL);
ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false,
0666);
if (cpulist == posscpus)
cpulist = NULL;
if (ret < 0) {
SYSERROR("Failed to write cpu list to \"%s\"", fpath);
return false;
}

TRACE("Copied cpu settings of parent cgroup");
}

return true;
Expand Down

0 comments on commit ada49c3

Please sign in to comment.