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