]> xenbits.xensource.com Git - libvirt.git/commitdiff
cgroup: Use system reported "unlimited" value for comparison
authorViktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Tue, 6 Dec 2016 12:03:29 +0000 (13:03 +0100)
committerMartin Kletzander <mkletzan@redhat.com>
Tue, 6 Dec 2016 15:25:20 +0000 (16:25 +0100)
With kernel 3.18 (since commit 3e32cb2e0a12b6915056ff04601cf1bb9b44f967)
the "unlimited" value for cgroup memory limits has changed once again as
its byte value is now computed from a page counter.
The new "unlimited" value reported by the cgroup fs is therefore 2**51-1
pages which is (VIR_DOMAIN_MEMORY_PARAM_UNLIMITED - 3072). This results
e.g. in virsh memtune displaying 9007199254740988 instead of unlimited
for the limits.

This patch uses the value of memory.limit_in_bytes from the cgroup
memory root which is the system's "real" unlimited value for comparison.

See also libvirt commit 231656bbeb9e4d3bedc44362784c35eee21cf0f4 for the
history for kernel 3.12 and before.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
src/util/vircgroup.c

index f151193401584f7298946d514a71b53e719d4ef7..b6affe37458d0e7d65034a2bbb9e888b6264e51f 100644 (file)
@@ -60,6 +60,7 @@
 #include "virsystemd.h"
 #include "virtypedparam.h"
 #include "virhostcpu.h"
+#include "virthread.h"
 
 VIR_LOG_INIT("util.cgroup");
 
@@ -2452,6 +2453,51 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
 }
 
 
+/*
+ * Retrieve the "memory.limit_in_bytes" value from the memory controller
+ * root dir. This value cannot be modified by userspace and therefore
+ * is the maximum limit value supported by cgroups on the local system.
+ * Returns this value scaled to KB or falls back to the original
+ * VIR_DOMAIN_MEMORY_PARAM_UNLIMITED. Either way, remember the return
+ * value to avoid unnecessary cgroup filesystem access.
+ */
+static unsigned long long int virCgroupMemoryUnlimitedKB;
+static virOnceControl virCgroupMemoryOnce = VIR_ONCE_CONTROL_INITIALIZER;
+
+static void
+virCgroupMemoryOnceInit(void)
+{
+    virCgroupPtr group;
+    unsigned long long int mem_unlimited = 0ULL;
+
+    if (virCgroupNew(-1, "/", NULL, -1, &group) < 0)
+        goto cleanup;
+
+    if (!virCgroupHasController(group, VIR_CGROUP_CONTROLLER_MEMORY))
+        goto cleanup;
+
+    ignore_value(virCgroupGetValueU64(group,
+                                      VIR_CGROUP_CONTROLLER_MEMORY,
+                                      "memory.limit_in_bytes",
+                                      &mem_unlimited));
+ cleanup:
+    virCgroupFree(&group);
+    virCgroupMemoryUnlimitedKB = mem_unlimited >> 10;
+}
+
+static unsigned long long int
+virCgroupGetMemoryUnlimitedKB(void)
+{
+    if (virOnce(&virCgroupMemoryOnce, virCgroupMemoryOnceInit) < 0)
+        VIR_DEBUG("Init failed, will fall back to defaults.");
+
+    if (virCgroupMemoryUnlimitedKB)
+        return virCgroupMemoryUnlimitedKB;
+    else
+        return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+}
+
+
 /**
  * virCgroupSetMemory:
  *
@@ -2534,20 +2580,17 @@ int
 virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
 {
     long long unsigned int limit_in_bytes;
-    int ret = -1;
 
     if (virCgroupGetValueU64(group,
                              VIR_CGROUP_CONTROLLER_MEMORY,
                              "memory.limit_in_bytes", &limit_in_bytes) < 0)
-        goto cleanup;
+        return -1;
 
     *kb = limit_in_bytes >> 10;
-    if (*kb > VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
+    if (*kb >= virCgroupGetMemoryUnlimitedKB())
         *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 
-    ret = 0;
- cleanup:
-    return ret;
+    return 0;
 }
 
 
@@ -2596,20 +2639,17 @@ int
 virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
 {
     long long unsigned int limit_in_bytes;
-    int ret = -1;
 
     if (virCgroupGetValueU64(group,
                              VIR_CGROUP_CONTROLLER_MEMORY,
                              "memory.soft_limit_in_bytes", &limit_in_bytes) < 0)
-        goto cleanup;
+        return -1;
 
     *kb = limit_in_bytes >> 10;
-    if (*kb > VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
+    if (*kb >= virCgroupGetMemoryUnlimitedKB())
         *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 
-    ret = 0;
- cleanup:
-    return ret;
+    return 0;
 }
 
 
@@ -2658,20 +2698,17 @@ int
 virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
 {
     long long unsigned int limit_in_bytes;
-    int ret = -1;
 
     if (virCgroupGetValueU64(group,
                              VIR_CGROUP_CONTROLLER_MEMORY,
                              "memory.memsw.limit_in_bytes", &limit_in_bytes) < 0)
-        goto cleanup;
+        return -1;
 
     *kb = limit_in_bytes >> 10;
-    if (*kb > VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
+    if (*kb >= virCgroupGetMemoryUnlimitedKB())
         *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
 
-    ret = 0;
- cleanup:
-    return ret;
+    return 0;
 }