Blame SOURCES/kvm-block-Activate-recursively-even-for-already-active-n.patch

ddf19c
From 0ef6691ce8964bb2bbd677756c4e594793ca3ad8 Mon Sep 17 00:00:00 2001
ddf19c
From: Kevin Wolf <kwolf@redhat.com>
ddf19c
Date: Fri, 7 Feb 2020 11:24:01 +0000
ddf19c
Subject: [PATCH 04/18] block: Activate recursively even for already active
ddf19c
 nodes
ddf19c
ddf19c
RH-Author: Kevin Wolf <kwolf@redhat.com>
ddf19c
Message-id: <20200207112404.25198-4-kwolf@redhat.com>
ddf19c
Patchwork-id: 93749
ddf19c
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH v2 3/6] block: Activate recursively even for already active nodes
ddf19c
Bugzilla: 1781637
ddf19c
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
ddf19c
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ddf19c
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ddf19c
ddf19c
bdrv_invalidate_cache_all() assumes that all nodes in a given subtree
ddf19c
are either active or inactive when it starts. Therefore, as soon as it
ddf19c
arrives at an already active node, it stops.
ddf19c
ddf19c
However, this assumption is wrong. For example, it's possible to take a
ddf19c
snapshot of an inactive node, which results in an active overlay over an
ddf19c
inactive backing file. The active overlay is probably also the root node
ddf19c
of an inactive BlockBackend (blk->disable_perm == true).
ddf19c
ddf19c
In this case, bdrv_invalidate_cache_all() does not need to do anything
ddf19c
to activate the overlay node, but it still needs to recurse into the
ddf19c
children and the parents to make sure that after returning success,
ddf19c
really everything is activated.
ddf19c
ddf19c
Cc: qemu-stable@nongnu.org
ddf19c
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ddf19c
Reviewed-by: Max Reitz <mreitz@redhat.com>
ddf19c
(cherry picked from commit 7bb4941ace471fc7dd6ded4749b95b9622baa6ed)
ddf19c
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ddf19c
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ddf19c
---
ddf19c
 block.c | 50 ++++++++++++++++++++++++--------------------------
ddf19c
 1 file changed, 24 insertions(+), 26 deletions(-)
ddf19c
ddf19c
diff --git a/block.c b/block.c
ddf19c
index 473eb6e..2e5e8b6 100644
ddf19c
--- a/block.c
ddf19c
+++ b/block.c
ddf19c
@@ -5335,10 +5335,6 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
ddf19c
         return;
ddf19c
     }
ddf19c
 
ddf19c
-    if (!(bs->open_flags & BDRV_O_INACTIVE)) {
ddf19c
-        return;
ddf19c
-    }
ddf19c
-
ddf19c
     QLIST_FOREACH(child, &bs->children, next) {
ddf19c
         bdrv_co_invalidate_cache(child->bs, &local_err);
ddf19c
         if (local_err) {
ddf19c
@@ -5360,34 +5356,36 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
ddf19c
      * just keep the extended permissions for the next time that an activation
ddf19c
      * of the image is tried.
ddf19c
      */
ddf19c
-    bs->open_flags &= ~BDRV_O_INACTIVE;
ddf19c
-    bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
ddf19c
-    ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err);
ddf19c
-    if (ret < 0) {
ddf19c
-        bs->open_flags |= BDRV_O_INACTIVE;
ddf19c
-        error_propagate(errp, local_err);
ddf19c
-        return;
ddf19c
-    }
ddf19c
-    bdrv_set_perm(bs, perm, shared_perm);
ddf19c
-
ddf19c
-    if (bs->drv->bdrv_co_invalidate_cache) {
ddf19c
-        bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
ddf19c
-        if (local_err) {
ddf19c
+    if (bs->open_flags & BDRV_O_INACTIVE) {
ddf19c
+        bs->open_flags &= ~BDRV_O_INACTIVE;
ddf19c
+        bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
ddf19c
+        ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err);
ddf19c
+        if (ret < 0) {
ddf19c
             bs->open_flags |= BDRV_O_INACTIVE;
ddf19c
             error_propagate(errp, local_err);
ddf19c
             return;
ddf19c
         }
ddf19c
-    }
ddf19c
+        bdrv_set_perm(bs, perm, shared_perm);
ddf19c
 
ddf19c
-    FOR_EACH_DIRTY_BITMAP(bs, bm) {
ddf19c
-        bdrv_dirty_bitmap_skip_store(bm, false);
ddf19c
-    }
ddf19c
+        if (bs->drv->bdrv_co_invalidate_cache) {
ddf19c
+            bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
ddf19c
+            if (local_err) {
ddf19c
+                bs->open_flags |= BDRV_O_INACTIVE;
ddf19c
+                error_propagate(errp, local_err);
ddf19c
+                return;
ddf19c
+            }
ddf19c
+        }
ddf19c
 
ddf19c
-    ret = refresh_total_sectors(bs, bs->total_sectors);
ddf19c
-    if (ret < 0) {
ddf19c
-        bs->open_flags |= BDRV_O_INACTIVE;
ddf19c
-        error_setg_errno(errp, -ret, "Could not refresh total sector count");
ddf19c
-        return;
ddf19c
+        FOR_EACH_DIRTY_BITMAP(bs, bm) {
ddf19c
+            bdrv_dirty_bitmap_skip_store(bm, false);
ddf19c
+        }
ddf19c
+
ddf19c
+        ret = refresh_total_sectors(bs, bs->total_sectors);
ddf19c
+        if (ret < 0) {
ddf19c
+            bs->open_flags |= BDRV_O_INACTIVE;
ddf19c
+            error_setg_errno(errp, -ret, "Could not refresh total sector count");
ddf19c
+            return;
ddf19c
+        }
ddf19c
     }
ddf19c
 
ddf19c
     QLIST_FOREACH(parent, &bs->parents, next_parent) {
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c