]> xenbits.xensource.com Git - libvirt.git/commitdiff
virnuma: Introduce virNumaSetPagePoolSize
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 18 Sep 2014 07:24:16 +0000 (09:24 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 25 Sep 2014 08:24:45 +0000 (10:24 +0200)
This internal API can be used to allocate or free some pages in
the huge pages pool.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
src/libvirt_private.syms
src/util/virnuma.c
src/util/virnuma.h

index d648ed3982ed8c0af40697cfe03f594d93d40fe6..6657d3d42e36b65a00093bdc8307e0e908627baa 100644 (file)
@@ -1719,6 +1719,7 @@ virNumaGetPageInfo;
 virNumaGetPages;
 virNumaIsAvailable;
 virNumaNodeIsAvailable;
+virNumaSetPagePoolSize;
 virNumaSetupMemoryPolicy;
 
 
index 1a3439807ed6705df4953f278517e9ea99ddabb7..690615f2e15ed3181bbc2076e65529de0b8b8e37 100644 (file)
@@ -841,6 +841,102 @@ virNumaGetPages(int node,
 }
 
 
+int
+virNumaSetPagePoolSize(int node,
+                       unsigned int page_size,
+                       unsigned long long page_count,
+                       bool add)
+{
+    int ret = -1;
+    char *nr_path = NULL, *nr_buf =  NULL;
+    char *end;
+    unsigned long long nr_count;
+
+    if (page_size == sysconf(_SC_PAGESIZE) / 1024) {
+        /* Special case as kernel handles system pages
+         * differently to huge pages. */
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("system pages pool can't be modified"));
+        goto cleanup;
+    }
+
+    if (virNumaGetHugePageInfoPath(&nr_path, node, page_size, "nr_hugepages") < 0)
+        goto cleanup;
+
+    /* Firstly check, if there's anything for us to do */
+    if (virFileReadAll(nr_path, 1024, &nr_buf) < 0)
+        goto cleanup;
+
+    if (virStrToLong_ull(nr_buf, &end, 10, &nr_count) < 0 ||
+        *end != '\n') {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       _("invalid number '%s' in '%s'"),
+                       nr_buf, nr_path);
+        goto cleanup;
+    }
+
+    if (add) {
+        if (!page_count) {
+            VIR_DEBUG("Nothing left to do: add = true page_count = 0");
+            ret = 0;
+            goto cleanup;
+        }
+        page_count += nr_count;
+    } else {
+        if (nr_count == page_count) {
+            VIR_DEBUG("Nothing left to do: nr_count = page_count = %llu",
+                      page_count);
+            ret = 0;
+            goto cleanup;
+        }
+    }
+
+    /* Okay, page pool adjustment must be done in two steps. In
+     * first we write the desired number into nr_hugepages file.
+     * Kernel then starts to allocate the pages (return from
+     * write should be postponed until the kernel is finished).
+     * However, kernel may have not been successful and reserved
+     * all the pages we wanted. So do the second read to check.
+     */
+    VIR_FREE(nr_buf);
+    if (virAsprintf(&nr_buf, "%llu", page_count) < 0)
+        goto cleanup;
+
+    if (virFileWriteStr(nr_path, nr_buf, 0) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to write to: %s"), nr_path);
+        goto cleanup;
+    }
+
+    /* And now do the check. */
+
+    VIR_FREE(nr_buf);
+    if (virFileReadAll(nr_path, 1024, &nr_buf) < 0)
+        goto cleanup;
+
+    if (virStrToLong_ull(nr_buf, &end, 10, &nr_count) < 0 ||
+        *end != '\n') {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       _("invalid number '%s' in '%s'"),
+                       nr_buf, nr_path);
+        goto cleanup;
+    }
+
+    if (nr_count != page_count) {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       _("Unable to allocate %llu pages. Allocated only %llu"),
+                       page_count, nr_count);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(nr_buf);
+    VIR_FREE(nr_path);
+    return ret;
+}
+
+
 #else /* #ifdef __linux__ */
 int
 virNumaGetPageInfo(int node ATTRIBUTE_UNUSED,
@@ -866,4 +962,16 @@ virNumaGetPages(int node ATTRIBUTE_UNUSED,
                    _("page info is not supported on this platform"));
     return -1;
 }
+
+
+int
+virNumaSetPagePoolSize(int node ATTRIBUTE_UNUSED,
+                       unsigned int page_size ATTRIBUTE_UNUSED,
+                       unsigned long long page_count ATTRIBUTE_UNUSED,
+                       bool add ATTRIBUTE_UNUSED)
+{
+    virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                   _("page pool allocation is not supported on this platform"));
+    return -1;
+}
 #endif /* #ifdef __linux__ */
index 13ebec6273a46dfe657a7fc8faf7423775de29d1..04b6b8c6ecfc46a663d666d9b7720af4f91f80bd 100644 (file)
@@ -59,4 +59,8 @@ int virNumaGetPages(int node,
                     unsigned int **pages_free,
                     size_t *npages)
     ATTRIBUTE_NONNULL(5);
+int virNumaSetPagePoolSize(int node,
+                           unsigned int page_size,
+                           unsigned long long page_count,
+                           bool add);
 #endif /* __VIR_NUMA_H__ */