Blame SOURCES/libvirt-qemu-block-Add-validator-for-bitmap-chains-accross-backing-chains.patch

fbe740
From eeb1315a8015aeda4d2fb7ce590c85c40ffb567d Mon Sep 17 00:00:00 2001
fbe740
Message-Id: <eeb1315a8015aeda4d2fb7ce590c85c40ffb567d@dist-git>
fbe740
From: Peter Krempa <pkrempa@redhat.com>
fbe740
Date: Tue, 4 Feb 2020 15:08:23 +0100
fbe740
Subject: [PATCH] qemu: block: Add validator for bitmap chains accross backing
fbe740
 chains
fbe740
MIME-Version: 1.0
fbe740
Content-Type: text/plain; charset=UTF-8
fbe740
Content-Transfer-Encoding: 8bit
fbe740
fbe740
Add a validator which checks that a bitmap spanning multiple backing
fbe740
chain members doesn't look broken. The current rules are that no
fbe740
intermediate birmaps are missing (unfortunately it's hard to know
fbe740
whether the topmost or bottommost bitmap is missing) and none of the
fbe740
components is inconsistent.
fbe740
fbe740
We can obviously improve it over time.
fbe740
fbe740
The validator is also tested against the existing bitmap data we have
fbe740
for the backup merging test as well as some of the existing broken
fbe740
bitmap synthetic test cases.
fbe740
fbe740
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
fbe740
Reviewed-by: Ján Tomko <jtomko@redhat.com>
fbe740
(cherry picked from commit 41c7e5c2a689a4ad091cec40b61beeeb3dde49b8)
fbe740
fbe740
https://bugzilla.redhat.com/show_bug.cgi?id=1207659
fbe740
Message-Id: <a1020495b33e99b2c1bb847dff26565d4def1e20.1580824112.git.pkrempa@redhat.com>
fbe740
Reviewed-by: Ján Tomko <jtomko@redhat.com>
fbe740
---
fbe740
 src/qemu/qemu_block.c | 41 +++++++++++++++++++++++++
fbe740
 src/qemu/qemu_block.h |  5 ++++
fbe740
 tests/qemublocktest.c | 70 +++++++++++++++++++++++++++++++++++++++++++
fbe740
 3 files changed, 116 insertions(+)
fbe740
fbe740
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
fbe740
index 03f029368e..b19290e677 100644
fbe740
--- a/src/qemu/qemu_block.c
fbe740
+++ b/src/qemu/qemu_block.c
fbe740
@@ -2687,3 +2687,44 @@ qemuBlockGetNamedNodeData(virDomainObjPtr vm,
fbe740
 
fbe740
     return g_steal_pointer(&blockNamedNodeData);
fbe740
 }
fbe740
+
fbe740
+
fbe740
+/**
fbe740
+ * qemuBlockBitmapChainIsValid:
fbe740
+ *
fbe740
+ * Validates that the backing chain of @src contains proper consistent bitmap
fbe740
+ * data for a chain of bitmaps named @bitmapname.
fbe740
+ *
fbe740
+ * A valid chain:
fbe740
+ * 1) bitmaps of same name are in a consecutive subset of images without gap
fbe740
+ * 2) don't have any inconsistent bitmaps
fbe740
+ */
fbe740
+bool
fbe740
+qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
fbe740
+                            const char *bitmapname,
fbe740
+                            virHashTablePtr blockNamedNodeData)
fbe740
+{
fbe740
+    qemuBlockNamedNodeDataBitmapPtr bitmap;
fbe740
+    virStorageSourcePtr n;
fbe740
+    bool chain_started = false;
fbe740
+    bool chain_ended = false;
fbe740
+
fbe740
+    for (n = src; n; n = n->backingStore) {
fbe740
+        if (!(bitmap = qemuBlockNamedNodeDataGetBitmapByName(blockNamedNodeData, n, bitmapname))) {
fbe740
+            if (chain_started)
fbe740
+                chain_ended = true;
fbe740
+
fbe740
+            continue;
fbe740
+        }
fbe740
+
fbe740
+        if (chain_ended)
fbe740
+            return false;
fbe740
+
fbe740
+        chain_started = true;
fbe740
+
fbe740
+        if (bitmap->inconsistent)
fbe740
+            return false;
fbe740
+    }
fbe740
+
fbe740
+    return chain_started;
fbe740
+}
fbe740
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
fbe740
index 68646cbf2e..cf51b9bf4e 100644
fbe740
--- a/src/qemu/qemu_block.h
fbe740
+++ b/src/qemu/qemu_block.h
fbe740
@@ -212,3 +212,8 @@ qemuBlockNamedNodeDataGetBitmapByName(virHashTablePtr blockNamedNodeData,
fbe740
 virHashTablePtr
fbe740
 qemuBlockGetNamedNodeData(virDomainObjPtr vm,
fbe740
                           qemuDomainAsyncJob asyncJob);
fbe740
+
fbe740
+bool
fbe740
+qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
fbe740
+                            const char *bitmapname,
fbe740
+                            virHashTablePtr blockNamedNodeData);
fbe740
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
fbe740
index 5946cd6c6b..6a7b07cfee 100644
fbe740
--- a/tests/qemublocktest.c
fbe740
+++ b/tests/qemublocktest.c
fbe740
@@ -764,6 +764,41 @@ testQemuCheckpointDeleteMerge(const void *opaque)
fbe740
 }
fbe740
 
fbe740
 
fbe740
+struct testQemuBlockBitmapValidateData {
fbe740
+    const char *name;
fbe740
+    const char *bitmapname;
fbe740
+    virStorageSourcePtr chain;
fbe740
+    bool expect;
fbe740
+};
fbe740
+
fbe740
+static int
fbe740
+testQemuBlockBitmapValidate(const void *opaque)
fbe740
+{
fbe740
+    const struct testQemuBlockBitmapValidateData *data = opaque;
fbe740
+    g_autoptr(virJSONValue) nodedatajson = NULL;
fbe740
+    g_autoptr(virHashTable) nodedata = NULL;
fbe740
+    bool actual;
fbe740
+
fbe740
+    if (!(nodedatajson = virTestLoadFileJSON(bitmapDetectPrefix, data->name,
fbe740
+                                             ".json", NULL)))
fbe740
+        return -1;
fbe740
+
fbe740
+    if (!(nodedata = qemuMonitorJSONBlockGetNamedNodeDataJSON(nodedatajson))) {
fbe740
+        VIR_TEST_VERBOSE("failed to load nodedata JSON\n");
fbe740
+        return -1;
fbe740
+    }
fbe740
+
fbe740
+    actual = qemuBlockBitmapChainIsValid(data->chain, data->bitmapname, nodedata);
fbe740
+
fbe740
+    if (actual != data->expect) {
fbe740
+        VIR_TEST_VERBOSE("expected rv:'%d' actual rv:'%d'\n", data->expect, actual);
fbe740
+        return -1;
fbe740
+    }
fbe740
+
fbe740
+    return 0;
fbe740
+}
fbe740
+
fbe740
+
fbe740
 static int
fbe740
 mymain(void)
fbe740
 {
fbe740
@@ -774,6 +809,7 @@ mymain(void)
fbe740
     struct testQemuImageCreateData imagecreatedata;
fbe740
     struct testQemuBackupIncrementalBitmapCalculateData backupbitmapcalcdata;
fbe740
     struct testQemuCheckpointDeleteMergeData checkpointdeletedata;
fbe740
+    struct testQemuBlockBitmapValidateData blockbitmapvalidatedata;
fbe740
     char *capslatest_x86_64 = NULL;
fbe740
     virQEMUCapsPtr caps_x86_64 = NULL;
fbe740
     g_autoptr(virStorageSource) bitmapSourceChain = NULL;
fbe740
@@ -1041,7 +1077,41 @@ mymain(void)
fbe740
     TEST_CHECKPOINT_DELETE_MERGE("snapshots-synthetic-checkpoint-intermediate3", "d", "c", "snapshots-synthetic-checkpoint");
fbe740
     TEST_CHECKPOINT_DELETE_MERGE("snapshots-synthetic-checkpoint-current", "current", "d", "snapshots-synthetic-checkpoint");
fbe740
 
fbe740
+#define TEST_BITMAP_VALIDATE(testname, bitmap, rc) \
fbe740
+    do { \
fbe740
+        blockbitmapvalidatedata.name = testname; \
fbe740
+        blockbitmapvalidatedata.chain = bitmapSourceChain; \
fbe740
+        blockbitmapvalidatedata.bitmapname = bitmap; \
fbe740
+        blockbitmapvalidatedata.expect = rc; \
fbe740
+        if (virTestRun("bitmap validate " testname " " bitmap, \
fbe740
+                       testQemuBlockBitmapValidate, \
fbe740
+                       &blockbitmapvalidatedata) < 0) \
fbe740
+            ret = -1; \
fbe740
+    } while (0)
fbe740
 
fbe740
+    TEST_BITMAP_VALIDATE("basic", "a", true);
fbe740
+    TEST_BITMAP_VALIDATE("basic", "b", true);
fbe740
+    TEST_BITMAP_VALIDATE("basic", "c", true);
fbe740
+    TEST_BITMAP_VALIDATE("basic", "d", true);
fbe740
+    TEST_BITMAP_VALIDATE("basic", "current", true);
fbe740
+
fbe740
+    TEST_BITMAP_VALIDATE("snapshots", "a", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots", "b", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots", "c", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots", "d", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots", "current", true);
fbe740
+
fbe740
+    TEST_BITMAP_VALIDATE("synthetic", "a", false);
fbe740
+    TEST_BITMAP_VALIDATE("synthetic", "b", true);
fbe740
+    TEST_BITMAP_VALIDATE("synthetic", "c", true);
fbe740
+    TEST_BITMAP_VALIDATE("synthetic", "d", true);
fbe740
+    TEST_BITMAP_VALIDATE("synthetic", "current", true);
fbe740
+
fbe740
+    TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "a", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "b", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "c", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "d", true);
fbe740
+    TEST_BITMAP_VALIDATE("snapshots-synthetic-checkpoint", "current", true);
fbe740
  cleanup:
fbe740
     virHashFree(diskxmljsondata.schema);
fbe740
     qemuTestDriverFree(&driver);
fbe740
-- 
fbe740
2.25.0
fbe740