c1c534
From fbecdf5ed4345a15d1ffc30922d44272a3d60368 Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <fbecdf5ed4345a15d1ffc30922d44272a3d60368@dist-git>
c1c534
From: Martin Kletzander <mkletzan@redhat.com>
c1c534
Date: Fri, 2 Feb 2018 15:21:27 +0100
c1c534
Subject: [PATCH] util: Clear unused part of the map in virBitmapShrink
c1c534
c1c534
Some of the other functions depend on the fact that unused bits and longs are
c1c534
always zero and it's less error-prone to clear it than fix the other functions.
c1c534
It's enough to zero out one piece of the map since we're calling realloc() to
c1c534
get rid of the rest (and updating map_len).
c1c534
c1c534
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1540817
c1c534
c1c534
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
c1c534
(cherry picked from commit d6e582da80d07a90f154dc27aca239d44fc2b7b7)
c1c534
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
c1c534
---
c1c534
 src/conf/domain_conf.c |  4 +++-
c1c534
 src/util/virbitmap.c   | 30 ++++++++++++++++++++++--------
c1c534
 src/util/virbitmap.h   |  2 +-
c1c534
 src/util/virresctrl.c  |  3 ++-
c1c534
 tests/virbitmaptest.c  |  8 ++++++++
c1c534
 5 files changed, 36 insertions(+), 11 deletions(-)
c1c534
c1c534
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
c1c534
index 181b035647..0af3dd5ab6 100644
c1c534
--- a/src/conf/domain_conf.c
c1c534
+++ b/src/conf/domain_conf.c
c1c534
@@ -18365,7 +18365,9 @@ virDomainCachetuneDefParse(virDomainDefPtr def,
c1c534
 
c1c534
     /* We need to limit the bitmap to number of vCPUs.  If there's nothing left,
c1c534
      * then we can just clean up and return 0 immediately */
c1c534
-    virBitmapShrink(vcpus, def->maxvcpus);
c1c534
+    if (virBitmapShrink(vcpus, def->maxvcpus) < 0)
c1c534
+        goto cleanup;
c1c534
+
c1c534
     if (virBitmapIsAllClear(vcpus)) {
c1c534
         ret = 0;
c1c534
         goto cleanup;
c1c534
diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
c1c534
index b2c5c7a6a5..33cae2f305 100644
c1c534
--- a/src/util/virbitmap.c
c1c534
+++ b/src/util/virbitmap.c
c1c534
@@ -1201,21 +1201,35 @@ virBitmapSubtract(virBitmapPtr a,
c1c534
 /**
c1c534
  * virBitmapShrink:
c1c534
  * @map: Pointer to bitmap
c1c534
- * @b: last bit position to be excluded from bitmap
c1c534
+ * @b: Size to reduce the bitmap to
c1c534
  *
c1c534
- * Resizes the bitmap so that no more than @b bits will fit into it.  Nothing
c1c534
- * will change if the size is already smaller than @b.
c1c534
- *
c1c534
- * NB: Does not adjust the map->map_len so that a subsequent virBitmapExpand
c1c534
- * doesn't necessarily need to reallocate.
c1c534
+ * Reduces the bitmap to size @b.  Nothing will change if the size is already
c1c534
+ * smaller than or equal to @b.
c1c534
  */
c1c534
-void
c1c534
+int
c1c534
 virBitmapShrink(virBitmapPtr map,
c1c534
                 size_t b)
c1c534
 {
c1c534
+    size_t nl = 0;
c1c534
+    size_t nb = 0;
c1c534
+
c1c534
     if (!map)
c1c534
-        return;
c1c534
+        return 0;
c1c534
 
c1c534
     if (map->max_bit >= b)
c1c534
         map->max_bit = b;
c1c534
+
c1c534
+    nl = map->max_bit / VIR_BITMAP_BITS_PER_UNIT;
c1c534
+    nb = map->max_bit % VIR_BITMAP_BITS_PER_UNIT;
c1c534
+    map->map[nl] &= ((1UL << nb) - 1);
c1c534
+
c1c534
+    nl++;
c1c534
+    if (nl == map->map_len)
c1c534
+        return 0;
c1c534
+
c1c534
+    if (VIR_REALLOC_N(map->map, nl) < 0)
c1c534
+        return -1;
c1c534
+
c1c534
+    map->map_len = nl;
c1c534
+    return 0;
c1c534
 }
c1c534
diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h
c1c534
index 2464814055..5a3362a19f 100644
c1c534
--- a/src/util/virbitmap.h
c1c534
+++ b/src/util/virbitmap.h
c1c534
@@ -153,6 +153,6 @@ void virBitmapIntersect(virBitmapPtr a, virBitmapPtr b)
c1c534
 void virBitmapSubtract(virBitmapPtr a, virBitmapPtr b)
c1c534
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c1c534
 
c1c534
-void virBitmapShrink(virBitmapPtr map, size_t b);
c1c534
+int virBitmapShrink(virBitmapPtr map, size_t b);
c1c534
 
c1c534
 #endif
c1c534
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
c1c534
index 70426199ce..ef388757a7 100644
c1c534
--- a/src/util/virresctrl.c
c1c534
+++ b/src/util/virresctrl.c
c1c534
@@ -941,7 +941,8 @@ virResctrlAllocParseProcessCache(virResctrlInfoPtr resctrl,
c1c534
     if (!mask)
c1c534
         return -1;
c1c534
 
c1c534
-    virBitmapShrink(mask, resctrl->levels[level]->types[type]->bits);
c1c534
+    if (virBitmapShrink(mask, resctrl->levels[level]->types[type]->bits) < 0)
c1c534
+        goto cleanup;
c1c534
 
c1c534
     if (virResctrlAllocUpdateMask(alloc, level, type, cache_id, mask) < 0)
c1c534
         goto cleanup;
c1c534
diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
c1c534
index 5bf30b2b1c..a78e4da723 100644
c1c534
--- a/tests/virbitmaptest.c
c1c534
+++ b/tests/virbitmaptest.c
c1c534
@@ -656,6 +656,14 @@ test12(const void *opaque ATTRIBUTE_UNUSED)
c1c534
 
c1c534
     TEST_MAP(1024, "34,1023");
c1c534
 
c1c534
+    if (virBitmapShrink(map, 35) < 0)
c1c534
+        goto cleanup;
c1c534
+    TEST_MAP(35, "34");
c1c534
+
c1c534
+    if (virBitmapShrink(map, 34) < 0)
c1c534
+        goto cleanup;
c1c534
+    TEST_MAP(34, "");
c1c534
+
c1c534
     ret = 0;
c1c534
 
c1c534
  cleanup:
c1c534
-- 
c1c534
2.16.1
c1c534