|
|
4e77bf |
From 0c98909e23aa8d3340b5752f2e774c9c966ff131 Mon Sep 17 00:00:00 2001
|
|
|
4e77bf |
Message-Id: <0c98909e23aa8d3340b5752f2e774c9c966ff131@dist-git>
|
|
|
4e77bf |
From: Michal Privoznik <mprivozn@redhat.com>
|
|
|
4e77bf |
Date: Fri, 25 May 2018 14:44:04 +0200
|
|
|
4e77bf |
Subject: [PATCH] virNumaGetHugePageInfo: Return page_avail and page_free as
|
|
|
4e77bf |
ULL
|
|
|
4e77bf |
MIME-Version: 1.0
|
|
|
4e77bf |
Content-Type: text/plain; charset=UTF-8
|
|
|
4e77bf |
Content-Transfer-Encoding: 8bit
|
|
|
4e77bf |
|
|
|
4e77bf |
RHEL-7.6: https://bugzilla.redhat.com/show_bug.cgi?id=1569678
|
|
|
4e77bf |
RHEL-7.5.z: https://bugzilla.redhat.com/show_bug.cgi?id=1582418
|
|
|
4e77bf |
|
|
|
4e77bf |
On some large systems (with ~400GB of RAM) it is possible for
|
|
|
4e77bf |
unsigned int to overflow in which case we report invalid number
|
|
|
4e77bf |
of 4K pages pool size. Switch to unsigned long long.
|
|
|
4e77bf |
|
|
|
4e77bf |
We hit overflow in virNumaGetPages when doing:
|
|
|
4e77bf |
|
|
|
4e77bf |
huge_page_sum += 1024 * page_size * page_avail;
|
|
|
4e77bf |
|
|
|
4e77bf |
because although 'huge_page_sum' is an unsigned long long, the
|
|
|
4e77bf |
page_size and page_avail are both unsigned int, so the promotion
|
|
|
4e77bf |
to unsigned long long doesn't happen until the sum has been
|
|
|
4e77bf |
calculated, by which time we've already overflowed.
|
|
|
4e77bf |
|
|
|
4e77bf |
Turning page_avail into a unsigned long long is not strictly
|
|
|
4e77bf |
needed until we need ability to represent more than 2^32
|
|
|
4e77bf |
4k pages, which equates to 16 TB of RAM. That's not
|
|
|
4e77bf |
outside the realm of possibility, so makes sense that we
|
|
|
4e77bf |
change it to unsigned long long to avoid future problems.
|
|
|
4e77bf |
|
|
|
4e77bf |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
4e77bf |
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
|
4e77bf |
(cherry picked from commit 31daccf5a550e7ede35532004006b34ba5c5b92e)
|
|
|
4e77bf |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
4e77bf |
---
|
|
|
4e77bf |
src/conf/capabilities.c | 5 +++--
|
|
|
4e77bf |
src/conf/capabilities.h | 2 +-
|
|
|
4e77bf |
src/util/virhostmem.c | 2 +-
|
|
|
4e77bf |
src/util/virnuma.c | 32 ++++++++++++++++++--------------
|
|
|
4e77bf |
src/util/virnuma.h | 8 ++++----
|
|
|
4e77bf |
tests/virnumamock.c | 4 ++--
|
|
|
4e77bf |
6 files changed, 29 insertions(+), 24 deletions(-)
|
|
|
4e77bf |
|
|
|
4e77bf |
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
|
|
|
4e77bf |
index edf9f54f77..66e2ecd151 100644
|
|
|
4e77bf |
--- a/src/conf/capabilities.c
|
|
|
4e77bf |
+++ b/src/conf/capabilities.c
|
|
|
4e77bf |
@@ -819,7 +819,7 @@ virCapabilitiesFormatNUMATopology(virBufferPtr buf,
|
|
|
4e77bf |
cells[i]->mem);
|
|
|
4e77bf |
|
|
|
4e77bf |
for (j = 0; j < cells[i]->npageinfo; j++) {
|
|
|
4e77bf |
- virBufferAsprintf(buf, "<pages unit='KiB' size='%u'>%zu</pages>\n",
|
|
|
4e77bf |
+ virBufferAsprintf(buf, "<pages unit='KiB' size='%u'>%llu</pages>\n",
|
|
|
4e77bf |
cells[i]->pageinfo[j].size,
|
|
|
4e77bf |
cells[i]->pageinfo[j].avail);
|
|
|
4e77bf |
}
|
|
|
4e77bf |
@@ -1354,7 +1354,8 @@ virCapabilitiesGetNUMAPagesInfo(int node,
|
|
|
4e77bf |
int *npageinfo)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
int ret = -1;
|
|
|
4e77bf |
- unsigned int *pages_size = NULL, *pages_avail = NULL;
|
|
|
4e77bf |
+ unsigned int *pages_size = NULL;
|
|
|
4e77bf |
+ unsigned long long *pages_avail = NULL;
|
|
|
4e77bf |
size_t npages, i;
|
|
|
4e77bf |
|
|
|
4e77bf |
if (virNumaGetPages(node, &pages_size, &pages_avail, NULL, &npages) < 0)
|
|
|
4e77bf |
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
|
|
|
4e77bf |
index 694a3590bf..f0a06a24df 100644
|
|
|
4e77bf |
--- a/src/conf/capabilities.h
|
|
|
4e77bf |
+++ b/src/conf/capabilities.h
|
|
|
4e77bf |
@@ -107,7 +107,7 @@ typedef struct _virCapsHostNUMACellPageInfo virCapsHostNUMACellPageInfo;
|
|
|
4e77bf |
typedef virCapsHostNUMACellPageInfo *virCapsHostNUMACellPageInfoPtr;
|
|
|
4e77bf |
struct _virCapsHostNUMACellPageInfo {
|
|
|
4e77bf |
unsigned int size; /* page size in kibibytes */
|
|
|
4e77bf |
- size_t avail; /* the size of pool */
|
|
|
4e77bf |
+ unsigned long long avail; /* the size of pool */
|
|
|
4e77bf |
};
|
|
|
4e77bf |
|
|
|
4e77bf |
typedef struct _virCapsHostNUMACell virCapsHostNUMACell;
|
|
|
4e77bf |
diff --git a/src/util/virhostmem.c b/src/util/virhostmem.c
|
|
|
4e77bf |
index a9ba2784ac..a795720954 100644
|
|
|
4e77bf |
--- a/src/util/virhostmem.c
|
|
|
4e77bf |
+++ b/src/util/virhostmem.c
|
|
|
4e77bf |
@@ -775,7 +775,7 @@ virHostMemGetFreePages(unsigned int npages,
|
|
|
4e77bf |
for (cell = startCell; cell <= lastCell; cell++) {
|
|
|
4e77bf |
for (i = 0; i < npages; i++) {
|
|
|
4e77bf |
unsigned int page_size = pages[i];
|
|
|
4e77bf |
- unsigned int page_free;
|
|
|
4e77bf |
+ unsigned long long page_free;
|
|
|
4e77bf |
|
|
|
4e77bf |
if (virNumaGetPageInfo(cell, page_size, 0, NULL, &page_free) < 0)
|
|
|
4e77bf |
goto cleanup;
|
|
|
4e77bf |
diff --git a/src/util/virnuma.c b/src/util/virnuma.c
|
|
|
4e77bf |
index bebe301f8d..784db0a7ce 100644
|
|
|
4e77bf |
--- a/src/util/virnuma.c
|
|
|
4e77bf |
+++ b/src/util/virnuma.c
|
|
|
4e77bf |
@@ -563,8 +563,8 @@ virNumaGetHugePageInfoDir(char **path, int node)
|
|
|
4e77bf |
static int
|
|
|
4e77bf |
virNumaGetHugePageInfo(int node,
|
|
|
4e77bf |
unsigned int page_size,
|
|
|
4e77bf |
- unsigned int *page_avail,
|
|
|
4e77bf |
- unsigned int *page_free)
|
|
|
4e77bf |
+ unsigned long long *page_avail,
|
|
|
4e77bf |
+ unsigned long long *page_free)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
int ret = -1;
|
|
|
4e77bf |
char *path = NULL;
|
|
|
4e77bf |
@@ -579,7 +579,7 @@ virNumaGetHugePageInfo(int node,
|
|
|
4e77bf |
if (virFileReadAll(path, 1024, &buf) < 0)
|
|
|
4e77bf |
goto cleanup;
|
|
|
4e77bf |
|
|
|
4e77bf |
- if (virStrToLong_ui(buf, &end, 10, page_avail) < 0 ||
|
|
|
4e77bf |
+ if (virStrToLong_ull(buf, &end, 10, page_avail) < 0 ||
|
|
|
4e77bf |
*end != '\n') {
|
|
|
4e77bf |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
4e77bf |
_("unable to parse: %s"),
|
|
|
4e77bf |
@@ -598,7 +598,7 @@ virNumaGetHugePageInfo(int node,
|
|
|
4e77bf |
if (virFileReadAll(path, 1024, &buf) < 0)
|
|
|
4e77bf |
goto cleanup;
|
|
|
4e77bf |
|
|
|
4e77bf |
- if (virStrToLong_ui(buf, &end, 10, page_free) < 0 ||
|
|
|
4e77bf |
+ if (virStrToLong_ull(buf, &end, 10, page_free) < 0 ||
|
|
|
4e77bf |
*end != '\n') {
|
|
|
4e77bf |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
4e77bf |
_("unable to parse: %s"),
|
|
|
4e77bf |
@@ -645,8 +645,8 @@ int
|
|
|
4e77bf |
virNumaGetPageInfo(int node,
|
|
|
4e77bf |
unsigned int page_size,
|
|
|
4e77bf |
unsigned long long huge_page_sum,
|
|
|
4e77bf |
- unsigned int *page_avail,
|
|
|
4e77bf |
- unsigned int *page_free)
|
|
|
4e77bf |
+ unsigned long long *page_avail,
|
|
|
4e77bf |
+ unsigned long long *page_free)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
int ret = -1;
|
|
|
4e77bf |
long system_page_size = virGetSystemPageSize();
|
|
|
4e77bf |
@@ -709,8 +709,8 @@ virNumaGetPageInfo(int node,
|
|
|
4e77bf |
int
|
|
|
4e77bf |
virNumaGetPages(int node,
|
|
|
4e77bf |
unsigned int **pages_size,
|
|
|
4e77bf |
- unsigned int **pages_avail,
|
|
|
4e77bf |
- unsigned int **pages_free,
|
|
|
4e77bf |
+ unsigned long long **pages_avail,
|
|
|
4e77bf |
+ unsigned long long **pages_free,
|
|
|
4e77bf |
size_t *npages)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
int ret = -1;
|
|
|
4e77bf |
@@ -718,7 +718,9 @@ virNumaGetPages(int node,
|
|
|
4e77bf |
DIR *dir = NULL;
|
|
|
4e77bf |
int direrr = 0;
|
|
|
4e77bf |
struct dirent *entry;
|
|
|
4e77bf |
- unsigned int *tmp_size = NULL, *tmp_avail = NULL, *tmp_free = NULL;
|
|
|
4e77bf |
+ unsigned int *tmp_size = NULL;
|
|
|
4e77bf |
+ unsigned long long *tmp_avail = NULL;
|
|
|
4e77bf |
+ unsigned long long *tmp_free = NULL;
|
|
|
4e77bf |
unsigned int ntmp = 0;
|
|
|
4e77bf |
size_t i;
|
|
|
4e77bf |
bool exchange;
|
|
|
4e77bf |
@@ -744,7 +746,9 @@ virNumaGetPages(int node,
|
|
|
4e77bf |
|
|
|
4e77bf |
while (dir && (direrr = virDirRead(dir, &entry, path)) > 0) {
|
|
|
4e77bf |
const char *page_name = entry->d_name;
|
|
|
4e77bf |
- unsigned int page_size, page_avail = 0, page_free = 0;
|
|
|
4e77bf |
+ unsigned int page_size;
|
|
|
4e77bf |
+ unsigned long long page_avail = 0;
|
|
|
4e77bf |
+ unsigned long long page_free = 0;
|
|
|
4e77bf |
char *end;
|
|
|
4e77bf |
|
|
|
4e77bf |
/* Just to give you a hint, we're dealing with this:
|
|
|
4e77bf |
@@ -934,8 +938,8 @@ int
|
|
|
4e77bf |
virNumaGetPageInfo(int node ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
unsigned int page_size ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
unsigned long long huge_page_sum ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
- unsigned int *page_avail ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
- unsigned int *page_free ATTRIBUTE_UNUSED)
|
|
|
4e77bf |
+ unsigned long long *page_avail ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
+ unsigned long long *page_free ATTRIBUTE_UNUSED)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
4e77bf |
_("page info is not supported on this platform"));
|
|
|
4e77bf |
@@ -946,8 +950,8 @@ virNumaGetPageInfo(int node ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
int
|
|
|
4e77bf |
virNumaGetPages(int node ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
unsigned int **pages_size ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
- unsigned int **pages_avail ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
- unsigned int **pages_free ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
+ unsigned long long **pages_avail ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
+ unsigned long long **pages_free ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
size_t *npages ATTRIBUTE_UNUSED)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
4e77bf |
diff --git a/src/util/virnuma.h b/src/util/virnuma.h
|
|
|
4e77bf |
index e4e1fd0b97..a3ffb6d6c7 100644
|
|
|
4e77bf |
--- a/src/util/virnuma.h
|
|
|
4e77bf |
+++ b/src/util/virnuma.h
|
|
|
4e77bf |
@@ -52,12 +52,12 @@ int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus) ATTRIBUTE_NOINLINE;
|
|
|
4e77bf |
int virNumaGetPageInfo(int node,
|
|
|
4e77bf |
unsigned int page_size,
|
|
|
4e77bf |
unsigned long long huge_page_sum,
|
|
|
4e77bf |
- unsigned int *page_avail,
|
|
|
4e77bf |
- unsigned int *page_free);
|
|
|
4e77bf |
+ unsigned long long *page_avail,
|
|
|
4e77bf |
+ unsigned long long *page_free);
|
|
|
4e77bf |
int virNumaGetPages(int node,
|
|
|
4e77bf |
unsigned int **pages_size,
|
|
|
4e77bf |
- unsigned int **pages_avail,
|
|
|
4e77bf |
- unsigned int **pages_free,
|
|
|
4e77bf |
+ unsigned long long **pages_avail,
|
|
|
4e77bf |
+ unsigned long long **pages_free,
|
|
|
4e77bf |
size_t *npages)
|
|
|
4e77bf |
ATTRIBUTE_NONNULL(5) ATTRIBUTE_NOINLINE;
|
|
|
4e77bf |
int virNumaSetPagePoolSize(int node,
|
|
|
4e77bf |
diff --git a/tests/virnumamock.c b/tests/virnumamock.c
|
|
|
4e77bf |
index d8f90b81b3..475efc1f34 100644
|
|
|
4e77bf |
--- a/tests/virnumamock.c
|
|
|
4e77bf |
+++ b/tests/virnumamock.c
|
|
|
4e77bf |
@@ -125,8 +125,8 @@ virNumaGetDistances(int node ATTRIBUTE_UNUSED,
|
|
|
4e77bf |
int
|
|
|
4e77bf |
virNumaGetPages(int node,
|
|
|
4e77bf |
unsigned int **pages_size,
|
|
|
4e77bf |
- unsigned int **pages_avail,
|
|
|
4e77bf |
- unsigned int **pages_free,
|
|
|
4e77bf |
+ unsigned long long **pages_avail,
|
|
|
4e77bf |
+ unsigned long long **pages_free,
|
|
|
4e77bf |
size_t *npages)
|
|
|
4e77bf |
{
|
|
|
4e77bf |
const int pages_def[] = { 4, 2 * 1024, 1 * 1024 * 1024};
|
|
|
4e77bf |
--
|
|
|
4e77bf |
2.17.1
|
|
|
4e77bf |
|