]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util: pull gnulib physmem impl into local code
authorDaniel P. Berrangé <berrange@redhat.com>
Wed, 8 Jan 2020 13:54:17 +0000 (13:54 +0000)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 17 Jan 2020 10:01:57 +0000 (10:01 +0000)
We don't need all the platforms gnulib deals with, so
this is a cut down version of GNULIB's physmem.c
code. This also allows us to integrate libvirt's
error reporting functions closer to the error cause.

Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
build-aux/syntax-check.mk
src/conf/capabilities.c
src/util/virhostcpu.c
src/util/virhostmem.c

index 687a4ef368a193f01981dfa868adfc26879f6fbb..359688ea544266bc787d9b582b035dbf297a02be 100644 (file)
@@ -2320,7 +2320,7 @@ exclude_file_name_regexp--sc_prohibit_virXXXFree = \
   ^(docs/|tests/|examples/|tools/|build-aux/syntax-check\.mk|src/test/test_driver.c|src/libvirt_public.syms|include/libvirt/libvirt-(domain|network|nodedev|storage|stream|secret|nwfilter|interface|domain-snapshot).h|src/libvirt-(domain|qemu|network|nodedev|storage|stream|secret|nwfilter|interface|domain-snapshot).c$$)
 
 exclude_file_name_regexp--sc_prohibit_sysconf_pagesize = \
-  ^(build-aux/syntax-check\.mk|src/util/virutil\.c)$$
+  ^(build-aux/syntax-check\.mk|src/util/vir(hostmem|util)\.c)$$
 
 exclude_file_name_regexp--sc_prohibit_pthread_create = \
   ^(build-aux/syntax-check\.mk|src/util/virthread\.c|tests/.*)$$
index 4bbc79334ec05d70d12b1e4ba370d21f918e29e5..d279ea05765b9e0c672fa25d3782d96f18cf606a 100644 (file)
@@ -26,7 +26,6 @@
 #include "capabilities.h"
 #include "cpu_conf.h"
 #include "domain_conf.h"
-#include "physmem.h"
 #include "storage_conf.h"
 #include "viralloc.h"
 #include "virarch.h"
index dd5016d4d27d0f70d380e983c567d55879db98d9..f9d5db59b96edd90807323e55788e6231b9cc551 100644 (file)
@@ -41,7 +41,6 @@
 #include "viralloc.h"
 #define LIBVIRT_VIRHOSTCPUPRIV_H_ALLOW
 #include "virhostcpupriv.h"
-#include "physmem.h"
 #include "virerror.h"
 #include "virarch.h"
 #include "virfile.h"
index 34e6f7adcf778b95a4f3db2d407572bd9805f15e..9c08b9bd78298d0ebfbce09e2ba5ad3ac7b52e53 100644 (file)
 # include <sys/resource.h>
 #endif
 
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
 #include "viralloc.h"
 #include "virhostmem.h"
-#include "physmem.h"
 #include "virerror.h"
 #include "virarch.h"
 #include "virfile.h"
@@ -577,13 +581,151 @@ virHostMemGetParameters(virTypedParameterPtr params G_GNUC_UNUSED,
 }
 
 
+#ifdef WIN32
+/*  MEMORYSTATUSEX is missing from older windows headers, so define
+    a local replacement.  */
+typedef struct
+{
+  DWORD dwLength;
+  DWORD dwMemoryLoad;
+  DWORDLONG ullTotalPhys;
+  DWORDLONG ullAvailPhys;
+  DWORDLONG ullTotalPageFile;
+  DWORDLONG ullAvailPageFile;
+  DWORDLONG ullTotalVirtual;
+  DWORDLONG ullAvailVirtual;
+  DWORDLONG ullAvailExtendedVirtual;
+} lMEMORYSTATUSEX;
+typedef WINBOOL(WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
+#endif /* !WIN32 */
+
+static unsigned long long
+virHostMemGetTotal(void)
+{
+#if defined HAVE_SYSCTLBYNAME
+    /* This works on freebsd & macOS. */
+    unsigned long long physmem = 0;
+    size_t len = sizeof(physmem);
+
+    if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to query memory total"));
+        return 0;
+    }
+
+    return physmem;
+#elif defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
+    /* this works on linux */
+    long long pages;
+    long long pagesize;
+    if ((pages = sysconf(_SC_PHYS_PAGES)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to query memory total"));
+        return 0;
+    }
+    if ((pagesize = sysconf(_SC_PAGESIZE)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to query memory page size"));
+        return 0;
+    }
+    return (unsigned long long)pages * (unsigned long long)pagesize;
+#elif defined WIN32
+    PFN_MS_EX pfnex;
+    HMODULE h = GetModuleHandle("kernel32.dll");
+
+    if (!h) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to access kernel32.dll"));
+        return 0;
+    }
+
+    /*  Use GlobalMemoryStatusEx if available.  */
+    if ((pfnex = (PFN_MS_EX) GetProcAddress(h, "GlobalMemoryStatusEx"))) {
+        lMEMORYSTATUSEX lms_ex;
+        lms_ex.dwLength = sizeof(lms_ex);
+        if (!pfnex(&lms_ex)) {
+            virReportSystemError(EIO, "%s",
+                                 _("Unable to query memory total"));
+            return 0;
+        }
+        return lms_ex.ullTotalPhys;
+    } else {
+        /*  Fall back to GlobalMemoryStatus which is always available.
+            but returns wrong results for physical memory > 4GB.  */
+        MEMORYSTATUS ms;
+        GlobalMemoryStatus(&ms);
+        return  ms.dwTotalPhys;
+    }
+#endif
+}
+
+
+static unsigned long long
+virHostMemGetAvailable(void)
+{
+#if defined HAVE_SYSCTLBYNAME
+    /* This works on freebsd and macOS */
+    unsigned long long usermem = 0;
+    size_t len = sizeof(usermem);
+
+    if (sysctlbyname("hw.usermem", &usermem, &len, NULL, 0) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to query memory available"));
+        return 0;
+    }
+
+    return usermem;
+#elif defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
+    /* this works on linux */
+    long long pages;
+    long long pagesize;
+    if ((pages = sysconf(_SC_AVPHYS_PAGES)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to query memory available"));
+        return 0;
+    }
+    if ((pagesize = sysconf(_SC_PAGESIZE)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to query memory page size"));
+        return 0;
+    }
+    return (unsigned long long)pages * (unsigned long long)pagesize;
+#elif defined WIN32
+    PFN_MS_EX pfnex;
+    HMODULE h = GetModuleHandle("kernel32.dll");
+
+    if (!h) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to access kernel32.dll"));
+        return 0;
+    }
+
+    /*  Use GlobalMemoryStatusEx if available.  */
+    if ((pfnex = (PFN_MS_EX) GetProcAddress(h, "GlobalMemoryStatusEx"))) {
+        lMEMORYSTATUSEX lms_ex;
+        lms_ex.dwLength = sizeof(lms_ex);
+        if (!pfnex(&lms_ex)) {
+            virReportSystemError(EIO, "%s",
+                                 _("Unable to query memory available"));
+            return 0;
+        }
+        return lms_ex.ullAvailPhys;
+    } else {
+        /*  Fall back to GlobalMemoryStatus which is always available.
+            but returns wrong results for physical memory > 4GB  */
+        MEMORYSTATUS ms;
+        GlobalMemoryStatus(&ms);
+        return ms.dwAvailPhys;
+    }
+#endif
+}
+
+
 static int
 virHostMemGetCellsFreeFake(unsigned long long *freeMems,
                            int startCell,
                            int maxCells G_GNUC_UNUSED)
 {
-    double avail = physmem_available();
-
     if (startCell != 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("start cell %d out of range (0-%d)"),
@@ -591,13 +733,8 @@ virHostMemGetCellsFreeFake(unsigned long long *freeMems,
         return -1;
     }
 
-    freeMems[0] = (unsigned long long)avail;
-
-    if (!freeMems[0]) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Cannot determine free memory"));
+    if ((freeMems[0] = virHostMemGetAvailable()) == 0)
         return -1;
-    }
 
     return 1;
 }
@@ -606,28 +743,13 @@ static int
 virHostMemGetInfoFake(unsigned long long *mem,
                       unsigned long long *freeMem)
 {
-    if (mem) {
-        double total = physmem_total();
-        if (!total) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("Cannot determine free memory"));
-            return -1;
-        }
-
-        *mem = (unsigned long long) total;
-    }
-
-    if (freeMem) {
-        double avail = physmem_available();
-
-        if (!avail) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("Cannot determine free memory"));
-            return -1;
-        }
+    if (mem &&
+        (*mem = virHostMemGetTotal()) == 0)
+        return -1;
 
-        *freeMem = (unsigned long long) avail;
-    }
+    if (freeMem &&
+        (*freeMem = virHostMemGetAvailable()) == 0)
+        return -1;
 
     return 0;
 }