From e65cb8ae214d26225acb853bfb628b1b7e0a825f Mon Sep 17 00:00:00 2001 From: LiFeng Date: Wed, 18 Dec 2019 22:37:08 -0500 Subject: [PATCH 134/139] lxc: do cpuset same as runc Signed-off-by: LiFeng --- src/lxc/cgroups/cgfsng.c | 288 +---------------------------------------------- 1 file changed, 3 insertions(+), 285 deletions(-) diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 5908c31..79fc5d3 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -248,288 +248,6 @@ static char *read_file(const char *fnam) return buf; } -/* Taken over modified from the kernel sources. */ -#define NBITS 32 /* bits in uint32_t */ -#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) -#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBITS) - -static void set_bit(unsigned bit, uint32_t *bitarr) -{ - bitarr[bit / NBITS] |= (1 << (bit % NBITS)); -} - -static void clear_bit(unsigned bit, uint32_t *bitarr) -{ - bitarr[bit / NBITS] &= ~(1 << (bit % NBITS)); -} - -static bool is_set(unsigned bit, uint32_t *bitarr) -{ - return (bitarr[bit / NBITS] & (1 << (bit % NBITS))) != 0; -} - -/* Create cpumask from cpulist aka turn: - * - * 0,2-3 - * - * into bit array - * - * 1 0 1 1 - */ -static uint32_t *lxc_cpumask(char *buf, size_t nbits) -{ - char *token; - size_t arrlen; - uint32_t *bitarr; - - arrlen = BITS_TO_LONGS(nbits); - bitarr = calloc(arrlen, sizeof(uint32_t)); - if (!bitarr) - return NULL; - - lxc_iterate_parts(token, buf, ",") { - errno = 0; - unsigned end, start; - char *range; - - start = strtoul(token, NULL, 0); - end = start; - range = strchr(token, '-'); - if (range) - end = strtoul(range + 1, NULL, 0); - - if (!(start <= end)) { - free(bitarr); - return NULL; - } - - if (end >= nbits) { - free(bitarr); - return NULL; - } - - while (start <= end) - set_bit(start++, bitarr); - } - - return bitarr; -} - -/* Turn cpumask into simple, comma-separated cpulist. */ -static char *lxc_cpumask_to_cpulist(uint32_t *bitarr, size_t nbits) -{ - int ret; - size_t i; - char **cpulist = NULL; - char numstr[INTTYPE_TO_STRLEN(size_t)] = {0}; - - for (i = 0; i <= nbits; i++) { - if (!is_set(i, bitarr)) - continue; - - ret = snprintf(numstr, sizeof(numstr), "%zu", i); - if (ret < 0 || (size_t)ret >= sizeof(numstr)) { - lxc_free_array((void **)cpulist, free); - return NULL; - } - - ret = lxc_append_string(&cpulist, numstr); - if (ret < 0) { - lxc_free_array((void **)cpulist, free); - return NULL; - } - } - - if (!cpulist) - return NULL; - - return lxc_string_join(",", (const char **)cpulist, false); -} - -static ssize_t get_max_cpus(char *cpulist) -{ - char *c1, *c2; - char *maxcpus = cpulist; - size_t cpus = 0; - - c1 = strrchr(maxcpus, ','); - if (c1) - c1++; - - c2 = strrchr(maxcpus, '-'); - if (c2) - c2++; - - if (!c1 && !c2) - c1 = maxcpus; - else if (c1 > c2) - c2 = c1; - else if (c1 < c2) - c1 = c2; - else if (!c1 && c2) - c1 = c2; - - errno = 0; - cpus = strtoul(c1, NULL, 0); - if (errno != 0) - return -1; - - return cpus; -} - -#define __ISOL_CPUS "/sys/devices/system/cpu/isolated" -static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized) -{ - int ret; - ssize_t i; - char *lastslash, *fpath, oldv; - ssize_t maxisol = 0, maxposs = 0; - char *cpulist = NULL, *isolcpus = NULL, *posscpus = NULL; - uint32_t *isolmask = NULL, *possmask = NULL; - bool bret = false, flipped_bit = false; - bool need_read_parent = false; - - fpath = must_make_path(path, "cpuset.cpus", NULL); - posscpus = read_file(fpath); - if (!posscpus) { - SYSERROR("Failed to read file \"%s\"", fpath); - goto on_error; - } - - if (strcmp(posscpus, "\n") == 0) { - need_read_parent = true; - free(fpath); - free(posscpus); - lastslash = strrchr(path, '/'); - if (!lastslash) { - ERROR("Failed to detect \"/\" in \"%s\"", path); - return bret; - } - oldv = *lastslash; - *lastslash = '\0'; - fpath = must_make_path(path, "cpuset.cpus", NULL); - posscpus = read_file(fpath); - if (!posscpus) { - SYSERROR("Failed to read file \"%s\"", fpath); - goto on_error; - } - } - - /* Get maximum number of cpus found in possible cpuset. */ - maxposs = get_max_cpus(posscpus); - if (maxposs < 0 || maxposs >= INT_MAX - 1) - goto on_error; - - 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"); - cpulist = posscpus; - /* 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"); - goto copy_parent; - } - /* No isolated cpus but we were already initialized by someone. - * Nothing more to do for us. - */ - goto on_success; - } - - isolcpus = read_file(__ISOL_CPUS); - if (!isolcpus) { - SYSERROR("Failed to read file \""__ISOL_CPUS"\""); - goto on_error; - } - if (!isdigit(isolcpus[0])) { - TRACE("No isolated cpus detected"); - cpulist = posscpus; - /* 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"); - goto copy_parent; - } - /* No isolated cpus but we were already initialized by someone. - * Nothing more to do for us. - */ - goto on_success; - } - - /* Get maximum number of cpus found in isolated cpuset. */ - maxisol = get_max_cpus(isolcpus); - if (maxisol < 0 || maxisol >= INT_MAX - 1) - goto on_error; - - if (maxposs < maxisol) - maxposs = maxisol; - maxposs++; - - possmask = lxc_cpumask(posscpus, maxposs); - if (!possmask) { - ERROR("Failed to create cpumask for possible cpus"); - goto on_error; - } - - isolmask = lxc_cpumask(isolcpus, maxposs); - if (!isolmask) { - ERROR("Failed to create cpumask for isolated cpus"); - goto on_error; - } - - for (i = 0; i <= maxposs; i++) { - if (!is_set(i, isolmask) || !is_set(i, possmask)) - continue; - - flipped_bit = true; - clear_bit(i, possmask); - } - - if (!flipped_bit) { - DEBUG("No isolated cpus present in cpuset"); - goto on_success; - } - DEBUG("Removed isolated cpus from cpuset"); - - cpulist = lxc_cpumask_to_cpulist(possmask, maxposs); - if (!cpulist) { - ERROR("Failed to create cpu list"); - goto on_error; - } - -copy_parent: - if (need_read_parent) { - *lastslash = oldv; - } - free(fpath); - fpath = must_make_path(path, "cpuset.cpus", NULL); - ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false, 0666); - if (ret < 0) { - SYSERROR("Failed to write cpu list to \"%s\"", fpath); - goto on_error; - } - -on_success: - bret = true; - -on_error: - free(fpath); - - free(isolcpus); - free(isolmask); - - if (posscpus != cpulist) - free(posscpus); - free(possmask); - - free(cpulist); - return bret; -} - /* Copy contents of parent(@path)/@file to @path/@file */ static bool copy_parent_file(char *path, char *file) { @@ -603,9 +321,9 @@ static bool build_sub_cpuset_cgroup_dir(char *cgpath) } } - /* Make sure any isolated cpus are removed from cpuset.cpus. */ - if (!cg_legacy_filter_and_set_cpus(cgpath, false)) { - SYSERROR("Failed to remove isolated cpus"); + /* copy parent's settings */ + if (!copy_parent_file(cgpath, "cpuset.cpus")) { + SYSERROR("Failed to copy \"cpuset.cpus\" settings"); return false; } -- 1.8.3.1