This internal API can be used to allocate or free some pages in
the huge pages pool.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virnuma.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virnuma.h | 4 ++
3 files changed, 113 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 51a692b..aabc11f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1699,6 +1699,7 @@ virNumaGetPageInfo;
virNumaGetPages;
virNumaIsAvailable;
virNumaNodeIsAvailable;
+virNumaSetPagePoolSize;
virNumaSetupMemoryPolicy;
diff --git a/src/util/virnuma.c b/src/util/virnuma.c
index 1a34398..690615f 100644
--- a/src/util/virnuma.c
+++ b/src/util/virnuma.c
@@ -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__ */
diff --git a/src/util/virnuma.h b/src/util/virnuma.h
index 13ebec6..04b6b8c 100644
--- a/src/util/virnuma.h
+++ b/src/util/virnuma.h
@@ -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__ */
--
1.8.5.5