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