]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virhostmem: Introduce virHostMemGetTHPSize()
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 20 Jan 2021 10:30:34 +0000 (11:30 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 1 Oct 2021 08:58:27 +0000 (10:58 +0200)
New virHostMemGetTHPSize() is introduced which allows caller to
obtain THP PMD (Page Middle Directory) size, which is equal to
the minimal size that THP can use, taken from kernel doc
(Documentation/admin-guide/mm/transhuge.rst):

  Some userspace (such as a test program, or an optimized memory allocation
  library) may want to know the size (in bytes) of a transparent hugepage::

    cat /sys/kernel/mm/transparent_hugepage/hpage_pmd_size

Since this size depends on the host architecture and the kernel
it won't change whilst libvirtd is running. Therefore, we can use
virOnce() and cache the value. Of course, we can be running under
kernel that has THP disabled or has no notion of THP at all. In
that case a negative value is returned to signal error.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/libvirt_private.syms
src/util/virhostmem.c
src/util/virhostmem.h
tests/domaincapsmock.c

index 6de9d9aef1ef43eac46a0d014761cbe4cad866d8..8b29b66a11a3710654f0618b6e478b016cba0618 100644 (file)
@@ -2412,6 +2412,7 @@ virHostMemGetFreePages;
 virHostMemGetInfo;
 virHostMemGetParameters;
 virHostMemGetStats;
+virHostMemGetTHPSize;
 virHostMemSetParameters;
 
 
index b13c3fe38e331c58ce3b81e1339bec8c713586f2..5984dfab3f8b1b591614f8b61034c5bff4fba5b4 100644 (file)
 #include "virstring.h"
 #include "virnuma.h"
 #include "virlog.h"
+#include "virthread.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 VIR_LOG_INIT("util.hostmem");
 
+static unsigned long long virHostTHPPMDSize; /* in kibibytes */
+static virOnceControl virHostMemGetTHPSizeOnce = VIR_ONCE_CONTROL_INITIALIZER;
 
 #ifdef __FreeBSD__
 # define BSD_MEMORY_STATS_ALL 4
@@ -930,3 +933,54 @@ virHostMemAllocPages(unsigned int npages,
 
     return ncounts;
 }
+
+#if defined(__linux__)
+# define HPAGE_PMD_SIZE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size"
+static void
+virHostMemGetTHPSizeSysfs(unsigned long long *size)
+{
+    if (virFileReadValueUllong(size, "%s", HPAGE_PMD_SIZE_PATH) < 0) {
+        VIR_WARN("unable to get THP PMD size: %s", g_strerror(errno));
+        return;
+    }
+
+    /* Size is now in bytes. Convert to KiB. */
+    *size >>= 10;
+}
+#endif /* defined(__linux__) */
+
+
+static void
+virHostMemGetTHPSizeOnceInit(void)
+{
+#if defined(__linux__)
+    virHostMemGetTHPSizeSysfs(&virHostTHPPMDSize);
+#else /* !defined(__linux__) */
+    VIR_WARN("Getting THP size not ported yet");
+#endif /* !defined(__linux__) */
+}
+
+
+/**
+ * virHostMemGetTHPSize:
+ * @size: returned size of THP in kibibytes
+ *
+ * Obtain Transparent Huge Page size in kibibytes. The size
+ * depends on host architecture and kernel. Because of virOnce(),
+ * do not rely on errno in case of failure.
+ *
+ * Returns: 0 on success,
+ *         -1 on failure.
+ */
+int
+virHostMemGetTHPSize(unsigned long long *size)
+{
+    if (virOnce(&virHostMemGetTHPSizeOnce, virHostMemGetTHPSizeOnceInit) < 0)
+        return -1;
+
+    if (virHostTHPPMDSize == 0)
+        return -1;
+
+    *size = virHostTHPPMDSize;
+    return 0;
+}
index 3265215d84bbdb61254b2299e348f1e00abc052c..c36de94f0f823ed572c0f4f02ff8b545a7cafd2a 100644 (file)
@@ -55,3 +55,6 @@ int virHostMemAllocPages(unsigned int npages,
                          unsigned int cellCount,
                          int lastCell,
                          bool add);
+
+int virHostMemGetTHPSize(unsigned long long *size)
+    G_GNUC_NO_INLINE;
index 0a6c541f77fcb585cf33b9f30fc01c39138c52ee..d382d06e2718523f25e3c624e005954bbac297a2 100644 (file)
@@ -17,6 +17,7 @@
 #include <config.h>
 
 #include "virhostcpu.h"
+#include "virhostmem.h"
 
 #if WITH_QEMU
 # include "virmock.h"
@@ -51,3 +52,11 @@ virQEMUCapsGetKVMSupportsSecureGuest(virQEMUCaps *qemuCaps)
     return real_virQEMUCapsGetKVMSupportsSecureGuest(qemuCaps);
 }
 #endif
+
+int
+virHostMemGetTHPSize(unsigned long long *size)
+{
+    /* Pretend Transparent Huge Page size is 2MiB. */
+    *size = 2048;
+    return 0;
+}