Blame SOURCES/kvm-block-qcow2-bitmap-Allow-resizes-with-persistent-bit.patch

7711c0
From ad64bca4d6cc7a258a546112b9494e6bfdf6cfbe Mon Sep 17 00:00:00 2001
7711c0
From: John Snow <jsnow@redhat.com>
7711c0
Date: Wed, 3 Apr 2019 22:42:51 +0200
7711c0
Subject: [PATCH 156/163] block/qcow2-bitmap: Allow resizes with persistent
7711c0
 bitmaps
7711c0
7711c0
RH-Author: John Snow <jsnow@redhat.com>
7711c0
Message-id: <20190403224253.5251-4-jsnow@redhat.com>
7711c0
Patchwork-id: 85433
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 3/5] block/qcow2-bitmap: Allow resizes with persistent bitmaps
7711c0
Bugzilla: 1666884
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
7711c0
7711c0
Since we now load all bitmaps into memory anyway, we can just truncate
7711c0
them in-memory and then flush them back to disk. Just in case, we will
7711c0
still check and enforce that this shortcut is valid -- i.e. that any
7711c0
bitmap described on-disk is indeed in-memory and can be modified.
7711c0
7711c0
If there are any inconsistent bitmaps, we refuse to allow the truncate
7711c0
as we do not actually load these bitmaps into memory, and it isn't safe
7711c0
or reasonable to attempt to truncate corrupted data.
7711c0
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
Message-id: 20190311185147.52309-4-vsementsov@virtuozzo.com
7711c0
  [vsementsov: drop bitmap flushing, fix block comments style]
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
(cherry picked from commit d19c6b36ffe09cec7ce7ac6a3e979bfe923ebba9)
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 block/qcow2-bitmap.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
7711c0
 block/qcow2.c        |  4 +---
7711c0
 block/qcow2.h        |  1 +
7711c0
 3 files changed, 48 insertions(+), 3 deletions(-)
7711c0
7711c0
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
7711c0
index fe4a6a2..3150855 100644
7711c0
--- a/block/qcow2-bitmap.c
7711c0
+++ b/block/qcow2-bitmap.c
7711c0
@@ -1176,6 +1176,52 @@ int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp)
7711c0
     return qcow2_reopen_bitmaps_rw_hint(bs, NULL, errp);
7711c0
 }
7711c0
 
7711c0
+/* Checks to see if it's safe to resize bitmaps */
7711c0
+int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp)
7711c0
+{
7711c0
+    BDRVQcow2State *s = bs->opaque;
7711c0
+    Qcow2BitmapList *bm_list;
7711c0
+    Qcow2Bitmap *bm;
7711c0
+    int ret = 0;
7711c0
+
7711c0
+    if (s->nb_bitmaps == 0) {
7711c0
+        return 0;
7711c0
+    }
7711c0
+
7711c0
+    bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
7711c0
+                               s->bitmap_directory_size, errp);
7711c0
+    if (bm_list == NULL) {
7711c0
+        return -EINVAL;
7711c0
+    }
7711c0
+
7711c0
+    QSIMPLEQ_FOREACH(bm, bm_list, entry) {
7711c0
+        BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(bs, bm->name);
7711c0
+        if (bitmap == NULL) {
7711c0
+            /*
7711c0
+             * We rely on all bitmaps being in-memory to be able to resize them,
7711c0
+             * Otherwise, we'd need to resize them on disk explicitly
7711c0
+             */
7711c0
+            error_setg(errp, "Cannot resize qcow2 with persistent bitmaps that "
7711c0
+                       "were not loaded into memory");
7711c0
+            ret = -ENOTSUP;
7711c0
+            goto out;
7711c0
+        }
7711c0
+
7711c0
+        /*
7711c0
+         * The checks against readonly and busy are redundant, but certainly
7711c0
+         * do no harm. checks against inconsistent are crucial:
7711c0
+         */
7711c0
+        if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
7711c0
+            ret = -ENOTSUP;
7711c0
+            goto out;
7711c0
+        }
7711c0
+    }
7711c0
+
7711c0
+out:
7711c0
+    bitmap_list_free(bm_list);
7711c0
+    return ret;
7711c0
+}
7711c0
+
7711c0
 /* store_bitmap_data()
7711c0
  * Store bitmap to image, filling bitmap table accordingly.
7711c0
  */
7711c0
diff --git a/block/qcow2.c b/block/qcow2.c
7711c0
index 21f7556..b137480 100644
7711c0
--- a/block/qcow2.c
7711c0
+++ b/block/qcow2.c
7711c0
@@ -3487,9 +3487,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
7711c0
     }
7711c0
 
7711c0
     /* cannot proceed if image has bitmaps */
7711c0
-    if (s->nb_bitmaps) {
7711c0
-        /* TODO: resize bitmaps in the image */
7711c0
-        error_setg(errp, "Can't resize an image which has bitmaps");
7711c0
+    if (qcow2_truncate_bitmaps_check(bs, errp)) {
7711c0
         ret = -ENOTSUP;
7711c0
         goto fail;
7711c0
     }
7711c0
diff --git a/block/qcow2.h b/block/qcow2.h
7711c0
index 2633e33..3b1b972 100644
7711c0
--- a/block/qcow2.h
7711c0
+++ b/block/qcow2.h
7711c0
@@ -681,6 +681,7 @@ Qcow2BitmapInfoList *qcow2_get_bitmap_info_list(BlockDriverState *bs,
7711c0
 int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, bool *header_updated,
7711c0
                                  Error **errp);
7711c0
 int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
7711c0
+int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
7711c0
 void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp);
7711c0
 int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
7711c0
 bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
7711c0
-- 
7711c0
1.8.3.1
7711c0