Blame SOURCES/libvirt-virNumaGetHugePageInfo-Return-page_avail-and-page_free-as-ULL.patch

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