diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index 89f73ff332..bb9bcb7916 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -1244,10 +1244,15 @@ bhyveConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED, static unsigned long long bhyveNodeGetFreeMemory(virConnectPtr conn) { + unsigned long long freeMem; + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) return 0; - return nodeGetFreeMemory(); + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + + return freeMem; } static int diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 19a2d654f6..6284d1181a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -877,8 +877,8 @@ nodeGetCPUBitmap; nodeGetCPUCount; nodeGetCPUMap; nodeGetCPUStats; -nodeGetFreeMemory; nodeGetInfo; +nodeGetMemory; nodeGetMemoryParameters; nodeGetMemoryStats; nodeSetMemoryParameters; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index d2852a7db6..ab227d0d0f 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -5477,10 +5477,15 @@ lxcNodeGetCellsFreeMemory(virConnectPtr conn, static unsigned long long lxcNodeGetFreeMemory(virConnectPtr conn) { + unsigned long long freeMem; + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) return 0; - return nodeGetFreeMemory(); + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + + return freeMem; } diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 5332edec7e..fd831b460a 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -1683,37 +1683,66 @@ nodeGetCellsFreeMemoryFake(unsigned long long *freeMems, return 1; } -static unsigned long long -nodeGetFreeMemoryFake(void) +static int +nodeGetMemoryFake(unsigned long long *mem, + unsigned long long *freeMem) { + int ret = -1; + #if defined(__FreeBSD__) unsigned long pagesize = getpagesize(); u_int value; size_t value_size = sizeof(value); - unsigned long long freemem; - if (sysctlbyname("vm.stats.vm.v_free_count", &value, - &value_size, NULL, 0) < 0) { - virReportSystemError(errno, "%s", - _("sysctl failed for vm.stats.vm.v_free_count")); - return 0; + if (mem) { + if (sysctlbyname("vm.stats.vm.v_page_count", &value, + &value_size, NULL, 0) < 0) { + virReportSystemError(errno, "%s", + _("sysctl failed for vm.stats.vm.v_page_count")); + goto cleanup; + } + *mem = value * (unsigned long long)pagesize; } - freemem = value * (unsigned long long)pagesize; + if (freeMem) { + if (sysctlbyname("vm.stats.vm.v_free_count", &value, + &value_size, NULL, 0) < 0) { + virReportSystemError(errno, "%s", + _("sysctl failed for vm.stats.vm.v_free_count")); + goto cleanup; + } + + *freeMem = value * (unsigned long long)pagesize; + } - return freemem; #else - double avail = physmem_available(); - unsigned long long ret; + if (mem) { + double total = physmem_total(); + if (!total) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot determine free memory")); + goto cleanup; + } - if (!(ret = (unsigned long long)avail)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot determine free memory")); - return 0; + *mem = (unsigned long long) total; } - return ret; + if (freeMem) { + double avail = physmem_available(); + + if (!avail) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot determine free memory")); + goto cleanup; + } + + *freeMem = (unsigned long long) avail; + } #endif + + ret = 0; + cleanup: + return ret; } /* returns 1 on success, 0 if the detection failed and -1 on hard error */ @@ -1914,25 +1943,40 @@ nodeGetCellsFreeMemory(unsigned long long *freeMems, return ret; } -unsigned long long -nodeGetFreeMemory(void) +int +nodeGetMemory(unsigned long long *mem, + unsigned long long *freeMem) { - unsigned long long mem; - unsigned long long freeMem = 0; int max_node; int n; + if (mem) + *mem = 0; + + if (freeMem) + *freeMem = 0; + if (!virNumaIsAvailable()) - return nodeGetFreeMemoryFake(); + return nodeGetMemoryFake(mem, freeMem); if ((max_node = virNumaGetMaxNode()) < 0) - return 0; + return -1; for (n = 0; n <= max_node; n++) { - virNumaGetNodeMemory(n, NULL, &mem); + unsigned long long tmp_mem = 0, tmp_freeMem = 0; - freeMem += mem; + if (!virNumaNodeIsAvailable(n)) + continue; + + if (virNumaGetNodeMemory(n, &tmp_mem, &tmp_freeMem) < 0) + return -1; + + if (mem) + *mem += tmp_mem; + + if (freeMem) + *freeMem += tmp_freeMem; } - return freeMem; + return 0; } diff --git a/src/nodeinfo.h b/src/nodeinfo.h index c81fcbb0f1..e7ec144f21 100644 --- a/src/nodeinfo.h +++ b/src/nodeinfo.h @@ -40,7 +40,8 @@ int nodeGetMemoryStats(int cellNum, int nodeGetCellsFreeMemory(unsigned long long *freeMems, int startCell, int maxCells); -unsigned long long nodeGetFreeMemory(void); +int nodeGetMemory(unsigned long long *mem, + unsigned long long *freeMem); virBitmapPtr nodeGetCPUBitmap(int *max_id); int nodeGetCPUCount(void); diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 87df2a71fc..4c815ed41e 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -2180,7 +2180,10 @@ openvzNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, static unsigned long long openvzNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) { - return nodeGetFreeMemory(); + unsigned long long freeMem; + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + return freeMem; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ca58d6bfd1..f359d8fd35 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -16605,10 +16605,15 @@ qemuNodeGetCellsFreeMemory(virConnectPtr conn, static unsigned long long qemuNodeGetFreeMemory(virConnectPtr conn) { + unsigned long long freeMem; + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) return 0; - return nodeGetFreeMemory(); + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + + return freeMem; } diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 1e0ec0e406..a5e9ea8b0f 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2806,10 +2806,15 @@ umlNodeGetCellsFreeMemory(virConnectPtr conn, static unsigned long long umlNodeGetFreeMemory(virConnectPtr conn) { + unsigned long long freeMem; + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) return 0; - return nodeGetFreeMemory(); + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + + return freeMem; } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 6365f2ab91..a80da69617 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -11476,7 +11476,10 @@ vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, static unsigned long long vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) { - return nodeGetFreeMemory(); + unsigned long long freeMem; + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + return freeMem; }