]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: block: implement helpers for blockdev-reopen
authorPeter Krempa <pkrempa@redhat.com>
Thu, 13 Feb 2020 08:24:36 +0000 (09:24 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 16 Mar 2020 16:33:08 +0000 (17:33 +0100)
Introduce a set of helpers to call blockdev-reopen in certain scenarios

Libvirt will use the QMP command to turn certain members of the backing
chain read-write for bitmap manipulation and we'll also want to use it
to replace/install the backing chain of a qcow2 format node.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
src/qemu/qemu_block.c
src/qemu/qemu_block.h

index 5ddf7f1f7c8ec584cf04a87e8b96dfa4dcaade88..9e41578a6e8e87310390aa6661b1f3d8e97f7e9b 100644 (file)
@@ -2988,3 +2988,104 @@ qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
 
     return 0;
 }
+
+
+/**
+ * qemuBlockReopenFormat:
+ * @vm: domain object
+ * @src: storage source to reopen
+ * @asyncJob: qemu async job type
+ *
+ * Invokes the 'blockdev-reopen' command on the format layer of @src. This means
+ * that @src must be already properly configured for the desired outcome. The
+ * nodenames of @src are used to identify the specific image in qemu.
+ */
+static int
+qemuBlockReopenFormat(virDomainObjPtr vm,
+                      virStorageSourcePtr src,
+                      qemuDomainAsyncJob asyncJob)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virQEMUDriverPtr driver = priv->driver;
+    g_autoptr(virJSONValue) reopenprops = NULL;
+    int rc;
+
+    /* If we are lacking the object here, qemu might have opened an image with
+     * a node name unknown to us */
+    if (!src->backingStore) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("can't reopen image with unknown presence of backing store"));
+        return -1;
+    }
+
+    if (!(reopenprops = qemuBlockStorageSourceGetBlockdevProps(src, src->backingStore)))
+        return -1;
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        return -1;
+
+    rc = qemuMonitorBlockdevReopen(priv->mon, &reopenprops);
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+        return -1;
+
+    return 0;
+}
+
+
+/**
+ * qemuBlockReopenReadWrite:
+ * @vm: domain object
+ * @src: storage source to reopen
+ * @asyncJob: qemu async job type
+ *
+ * Wrapper that reopens @src read-write. We currently depend on qemu
+ * reopening the storage with 'auto-read-only' enabled for us.
+ * After successful reopen @src's 'readonly' flag is modified. Does nothing
+ * if @src is already read-write.
+ */
+int
+qemuBlockReopenReadWrite(virDomainObjPtr vm,
+                         virStorageSourcePtr src,
+                         qemuDomainAsyncJob asyncJob)
+{
+    if (!src->readonly)
+        return 0;
+
+    src->readonly = false;
+    if (qemuBlockReopenFormat(vm, src, asyncJob) < 0) {
+        src->readonly = true;
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/**
+ * qemuBlockReopenReadOnly:
+ * @vm: domain object
+ * @src: storage source to reopen
+ * @asyncJob: qemu async job type
+ *
+ * Wrapper that reopens @src read-only. We currently depend on qemu
+ * reopening the storage with 'auto-read-only' enabled for us.
+ * After successful reopen @src's 'readonly' flag is modified. Does nothing
+ * if @src is already read-only.
+ */
+int
+qemuBlockReopenReadOnly(virDomainObjPtr vm,
+                         virStorageSourcePtr src,
+                         qemuDomainAsyncJob asyncJob)
+{
+    if (src->readonly)
+        return 0;
+
+    src->readonly = true;
+    if (qemuBlockReopenFormat(vm, src, asyncJob) < 0) {
+        src->readonly = false;
+        return -1;
+    }
+
+    return 0;
+}
index 197f5dae974efdd99bbb4271290ac2e840b1f97c..e012052352b2193007a0293b71d7be0f6c4c8b86 100644 (file)
@@ -231,3 +231,12 @@ qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
                                 virHashTablePtr blockNamedNodeData,
                                 bool shallow,
                                 virJSONValuePtr *actions);
+
+int
+qemuBlockReopenReadWrite(virDomainObjPtr vm,
+                         virStorageSourcePtr src,
+                         qemuDomainAsyncJob asyncJob);
+int
+qemuBlockReopenReadOnly(virDomainObjPtr vm,
+                        virStorageSourcePtr src,
+                        qemuDomainAsyncJob asyncJob);