]> git.proxmox.com Git - mirror_lxcfs.git/commitdiff
cpuinfo: use cpu view based on cpu quotas
authorJakub Skokan <jakub.skokan@havefun.cz>
Mon, 25 Jun 2018 06:54:15 +0000 (08:54 +0200)
committerJakub Skokan <jakub.skokan@havefun.cz>
Wed, 24 Oct 2018 12:06:22 +0000 (14:06 +0200)
Signed-off-by: Jakub Skokan <jakub.skokan@havefun.cz>
bindings.c

index 70386fc75f2804b91d9dd77d4d006421b35ab1c6..94f0ff7cb98ee4322c0fc8da9f5d865ae6c886e7 100644 (file)
@@ -3509,6 +3509,85 @@ static bool cpuline_in_cpuset(const char *line, const char *cpuset)
        return cpu_in_cpuset(cpu, cpuset);
 }
 
+/*
+ * Read cgroup CPU quota parameters from `cpu.cfs_quota_us` or `cpu.cfs_period_us`,
+ * depending on `param`. Parameter value is returned throuh `value`.
+ */
+static bool read_cpu_cfs_param(const char *cg, const char *param, int64_t *value)
+{
+       bool rv = false;
+       char file[11 + 6 + 1]; // cpu.cfs__us + quota/period + \0
+       char *str = NULL;
+
+       sprintf(file, "cpu.cfs_%s_us", param);
+
+       if (!cgfs_get_value("cpu", cg, file, &str))
+               goto err;
+
+       if (sscanf(str, "%ld", value) != 1)
+               goto err;
+
+       rv = true;
+
+err:
+       if (str)
+               free(str);
+       return rv;
+}
+
+/*
+ * Return the maximum number of visible CPUs based on CPU quotas.
+ * If there is no quota set, zero is returned.
+ */
+int max_cpu_count(const char *cg)
+{
+       int rv, nprocs;
+       int64_t cfs_quota, cfs_period;
+
+       if (!read_cpu_cfs_param(cg, "quota", &cfs_quota))
+               return 0;
+
+       if (!read_cpu_cfs_param(cg, "period", &cfs_period))
+               return 0;
+
+       if (cfs_quota <= 0 || cfs_period <= 0)
+               return 0;
+
+       rv = cfs_quota / cfs_period;
+
+       /* In case quota/period does not yield a whole number, add one CPU for
+        * the remainder.
+        */
+       if ((cfs_quota % cfs_period) > 0)
+               rv += 1;
+
+       nprocs = get_nprocs();
+
+       if (rv > nprocs)
+               rv = nprocs;
+
+       return rv;
+}
+
+/*
+ * Determine whether CPU views should be used or not.
+ */
+bool use_cpuview(const char *cg)
+{
+       int cfd;
+       char *tmpc;
+
+       tmpc = find_mounted_controller("cpu", &cfd);
+       if (!tmpc)
+               return false;
+
+       tmpc = find_mounted_controller("cpuacct", &cfd);
+       if (!tmpc)
+               return false;
+
+       return true;
+}
+
 /*
  * check whether this is a '^processor" line in /proc/cpuinfo
  */
@@ -3531,7 +3610,8 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset,
        char *line = NULL;
        size_t linelen = 0, total_len = 0, rv = 0;
        bool am_printing = false, firstline = true, is_s390x = false;
-       int curcpu = -1, cpu;
+       int curcpu = -1, cpu, max_cpus = 0;
+       bool use_view;
        char *cache = d->buf;
        size_t cache_size = d->buflen;
        FILE *f = NULL;
@@ -3559,6 +3639,11 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset,
        if (!cpuset)
                goto err;
 
+       use_view = use_cpuview(cg);
+
+       if (use_view)
+               max_cpus = max_cpu_count(cg);
+
        f = fopen("/proc/cpuinfo", "r");
        if (!f)
                goto err;
@@ -3576,6 +3661,8 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset,
                if (strncmp(line, "# processors:", 12) == 0)
                        continue;
                if (is_processor_line(line)) {
+                       if (use_view && max_cpus > 0 && (curcpu+1) == max_cpus)
+                               break;
                        am_printing = cpuline_in_cpuset(line, cpuset);
                        if (am_printing) {
                                curcpu ++;
@@ -3597,6 +3684,8 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset,
                        continue;
                } else if (is_s390x && sscanf(line, "processor %d:", &cpu) == 1) {
                        char *p;
+                       if (use_view && max_cpus > 0 && (curcpu+1) == max_cpus)
+                               break;
                        if (!cpu_in_cpuset(cpu, cpuset))
                                continue;
                        curcpu ++;