a41c76
From eee9a7173898212632d42ef74777d6726ce29d5f Mon Sep 17 00:00:00 2001
a41c76
Message-Id: <eee9a7173898212632d42ef74777d6726ce29d5f@dist-git>
a41c76
From: Peter Krempa <pkrempa@redhat.com>
a41c76
Date: Tue, 4 Feb 2020 15:08:15 +0100
a41c76
Subject: [PATCH] qemu: checkpoint: Track and relabel images for bitmap merging
a41c76
MIME-Version: 1.0
a41c76
Content-Type: text/plain; charset=UTF-8
a41c76
Content-Transfer-Encoding: 8bit
a41c76
a41c76
Allow qemu access to modify backing files in case when we want to delete
a41c76
a checkpoint.
a41c76
a41c76
This patch adds tracking of which images need to be relabelled when
a41c76
calculating the transaction, the code to relabel them and rollback.
a41c76
a41c76
To verify that stuff works we also output the list of images to relabel
a41c76
into the test case output files in qemublocktest.
a41c76
a41c76
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
a41c76
Reviewed-by: Ján Tomko <jtomko@redhat.com>
a41c76
(cherry picked from commit 8e94e290104ffb5d9db051ab0b0ff36f58dbc943)
a41c76
a41c76
https://bugzilla.redhat.com/show_bug.cgi?id=1207659
a41c76
Message-Id: <36c2dc7f5d0d59aac90b2e272983f72476b00661.1580824112.git.pkrempa@redhat.com>
a41c76
Reviewed-by: Ján Tomko <jtomko@redhat.com>
a41c76
---
a41c76
 src/qemu/qemu_checkpoint.c                    | 35 ++++++++++++++++---
a41c76
 src/qemu/qemu_checkpoint.h                    |  3 +-
a41c76
 tests/qemublocktest.c                         | 19 ++++++++--
a41c76
 .../snapshots-intermediate1-out.json          |  2 ++
a41c76
 .../snapshots-intermediate2-out.json          |  3 ++
a41c76
 .../snapshots-intermediate3-out.json          |  2 ++
a41c76
 .../snapshots-noparent-out.json               |  4 +++
a41c76
 ...ynthetic-checkpoint-intermediate1-out.json |  2 ++
a41c76
 ...ynthetic-checkpoint-intermediate2-out.json |  2 ++
a41c76
 ...ynthetic-checkpoint-intermediate3-out.json |  2 ++
a41c76
 ...ots-synthetic-checkpoint-noparent-out.json |  4 +++
a41c76
 11 files changed, 70 insertions(+), 8 deletions(-)
a41c76
a41c76
diff --git a/src/qemu/qemu_checkpoint.c b/src/qemu/qemu_checkpoint.c
a41c76
index 55061bbf76..59b7f63fdc 100644
a41c76
--- a/src/qemu/qemu_checkpoint.c
a41c76
+++ b/src/qemu/qemu_checkpoint.c
a41c76
@@ -155,7 +155,8 @@ qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src,
a41c76
                                  const char *delbitmap,
a41c76
                                  const char *parentbitmap,
a41c76
                                  virJSONValuePtr actions,
a41c76
-                                 const char *diskdst)
a41c76
+                                 const char *diskdst,
a41c76
+                                 GSList **reopenimages)
a41c76
 {
a41c76
     virStorageSourcePtr n = src;
a41c76
 
a41c76
@@ -235,6 +236,9 @@ qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src,
a41c76
                                                srcbitmap->name) < 0)
a41c76
             return -1;
a41c76
 
a41c76
+        if (n != src)
a41c76
+            *reopenimages = g_slist_prepend(*reopenimages, n);
a41c76
+
a41c76
         n = n->backingStore;
a41c76
     }
a41c76
 
a41c76
@@ -250,9 +254,12 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
a41c76
     qemuDomainObjPrivatePtr priv = vm->privateData;
a41c76
     virQEMUDriverPtr driver = priv->driver;
a41c76
     g_autoptr(virHashTable) blockNamedNodeData = NULL;
a41c76
-    int rc;
a41c76
+    int rc = -1;
a41c76
     g_autoptr(virJSONValue) actions = NULL;
a41c76
     size_t i;
a41c76
+    g_autoptr(GSList) reopenimages = NULL;
a41c76
+    g_autoptr(GSList) relabelimages = NULL;
a41c76
+    GSList *next;
a41c76
 
a41c76
     if (!(actions = virJSONValueNewArray()))
a41c76
         return -1;
a41c76
@@ -284,16 +291,34 @@ qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
a41c76
 
a41c76
         if (qemuCheckpointDiscardDiskBitmaps(domdisk->src, blockNamedNodeData,
a41c76
                                              chkdisk->bitmap, parentbitmap,
a41c76
-                                             actions, domdisk->dst) < 0)
a41c76
+                                             actions, domdisk->dst,
a41c76
+                                             &reopenimages) < 0)
a41c76
             return -1;
a41c76
     }
a41c76
 
a41c76
+    /* label any non-top images for read-write access */
a41c76
+    for (next = reopenimages; next; next = next->next) {
a41c76
+        virStorageSourcePtr src = next->data;
a41c76
+
a41c76
+        if (qemuDomainStorageSourceAccessAllow(driver, vm, src, false, false) < 0)
a41c76
+            goto relabel;
a41c76
+
a41c76
+        relabelimages = g_slist_prepend(relabelimages, src);
a41c76
+    }
a41c76
+
a41c76
     qemuDomainObjEnterMonitor(driver, vm);
a41c76
     rc = qemuMonitorTransaction(priv->mon, &actions);
a41c76
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
a41c76
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
a41c76
         return -1;
a41c76
 
a41c76
-    return 0;
a41c76
+ relabel:
a41c76
+    for (next = relabelimages; next; next = next->next) {
a41c76
+        virStorageSourcePtr src = next->data;
a41c76
+
a41c76
+        ignore_value(qemuDomainStorageSourceAccessAllow(driver, vm, src, true, false));
a41c76
+    }
a41c76
+
a41c76
+    return rc;
a41c76
 }
a41c76
 
a41c76
 
a41c76
diff --git a/src/qemu/qemu_checkpoint.h b/src/qemu/qemu_checkpoint.h
a41c76
index 976b1eed0f..cf1e9e46cb 100644
a41c76
--- a/src/qemu/qemu_checkpoint.h
a41c76
+++ b/src/qemu/qemu_checkpoint.h
a41c76
@@ -78,4 +78,5 @@ qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src,
a41c76
                                  const char *delbitmap,
a41c76
                                  const char *parentbitmap,
a41c76
                                  virJSONValuePtr actions,
a41c76
-                                 const char *diskdst);
a41c76
+                                 const char *diskdst,
a41c76
+                                 GSList **reopenimages);
a41c76
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
a41c76
index 2e5927f3c1..ed8b061e2e 100644
a41c76
--- a/tests/qemublocktest.c
a41c76
+++ b/tests/qemublocktest.c
a41c76
@@ -717,6 +717,9 @@ testQemuCheckpointDeleteMerge(const void *opaque)
a41c76
     g_autoptr(virJSONValue) actions = NULL;
a41c76
     g_autoptr(virJSONValue) nodedatajson = NULL;
a41c76
     g_autoptr(virHashTable) nodedata = NULL;
a41c76
+    g_autoptr(GSList) reopenimages = NULL;
a41c76
+    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
a41c76
+    GSList *tmp;
a41c76
 
a41c76
     expectpath = g_strdup_printf("%s/%s%s-out.json", abs_srcdir,
a41c76
                                  checkpointDeletePrefix, data->name);
a41c76
@@ -738,14 +741,26 @@ testQemuCheckpointDeleteMerge(const void *opaque)
a41c76
                                          data->deletebitmap,
a41c76
                                          data->parentbitmap,
a41c76
                                          actions,
a41c76
-                                         "testdisk") < 0) {
a41c76
+                                         "testdisk",
a41c76
+                                         &reopenimages) < 0) {
a41c76
         VIR_TEST_VERBOSE("failed to generate checkpoint delete transaction\n");
a41c76
         return -1;
a41c76
     }
a41c76
 
a41c76
-    if (!(actual = virJSONValueToString(actions, true)))
a41c76
+    if (virJSONValueToBuffer(actions, &buf, true) < 0)
a41c76
         return -1;
a41c76
 
a41c76
+    if (reopenimages) {
a41c76
+        virBufferAddLit(&buf, "reopen nodes:\n");
a41c76
+
a41c76
+        for (tmp = reopenimages; tmp; tmp = tmp->next) {
a41c76
+            virStorageSourcePtr src = tmp->data;
a41c76
+            virBufferAsprintf(&buf, "%s\n", src->nodeformat);
a41c76
+        }
a41c76
+    }
a41c76
+
a41c76
+    actual = virBufferContentAndReset(&buf;;
a41c76
+
a41c76
     return virTestCompareToFile(actual, expectpath);
a41c76
 }
a41c76
 
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json
a41c76
index 29fefeea63..c9bda3a17a 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate1-out.json
a41c76
@@ -20,3 +20,5 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-3-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json
a41c76
index 4da21a9df7..8a0e3f2cff 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate2-out.json
a41c76
@@ -57,3 +57,6 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-3-format
a41c76
+libvirt-2-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json
a41c76
index dc87dd60b8..211bc40baf 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-intermediate3-out.json
a41c76
@@ -57,3 +57,5 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-2-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json
a41c76
index 45a84b47c2..f750f44da2 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-noparent-out.json
a41c76
@@ -21,3 +21,7 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-5-format
a41c76
+libvirt-4-format
a41c76
+libvirt-3-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json
a41c76
index e979691e6f..d7e6d18637 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate1-out.json
a41c76
@@ -27,3 +27,5 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-3-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json
a41c76
index e82098918a..cfbff010c2 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate2-out.json
a41c76
@@ -30,3 +30,5 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-2-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json
a41c76
index dc87dd60b8..211bc40baf 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-intermediate3-out.json
a41c76
@@ -57,3 +57,5 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-2-format
a41c76
diff --git a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json
a41c76
index 45a84b47c2..f750f44da2 100644
a41c76
--- a/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json
a41c76
+++ b/tests/qemublocktestdata/checkpointdelete/snapshots-synthetic-checkpoint-noparent-out.json
a41c76
@@ -21,3 +21,7 @@
a41c76
     }
a41c76
   }
a41c76
 ]
a41c76
+reopen nodes:
a41c76
+libvirt-5-format
a41c76
+libvirt-4-format
a41c76
+libvirt-3-format
a41c76
-- 
a41c76
2.25.0
a41c76