[PATCH 1/3] qemu: implementation of transient option for qcow2 file

Masayoshi Mizuma msys.mizuma at gmail.com
Mon Jul 6 18:20:23 UTC 2020


From: Masayoshi Mizuma <m.mizuma at jp.fujitsu.com>

Here is the implementation of transient option for qcow2 file.
This gets available <transient/> directive in domain xml file
like as:

    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/guest.qcow2'/>
      <target dev='vda' bus='virtio'/>
      <transient/>
    </disk>

The internal procedure is as follows.
When the qemu command line options are built, a new qcow2 image is created
with backing qcow2 image by using qemu-img command. The backing image is the
qcow2 file which is set as <source>.
The filename of the new qcow2 image is original-source-file.TRANSIENT.
The qemu-img will be:

    qemu-img create -f qcow2 -F qcow2 \
            -b /var/lib/libvirt/images/guest.qcow2 \
            /var/lib/libvirt/images/guest.qcow2.TRANSIENT

Then, it switches the disk path, virStorageSourcePtr src->path, to
the new qcow2 image. The new image and the backing image is handled and
the blockdev option of qemu will be built like as:

    -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/guest.qcow2",
                "node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
    -blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"qcow2",
                "file":"libvirt-2-storage","backing":null}' \
    -blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/guest.qcow2.TRANSIENT",
                "node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
    -blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2",
                "file":"libvirt-1-storage","backing":"libvirt-2-format"}'

The new qcow2 image is removed when the Guest is shutdowned, 

Signed-off-by: Masayoshi Mizuma <m.mizuma at jp.fujitsu.com>
---
 src/qemu/qemu_block.c    | 71 ++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_block.h    |  7 ++++
 src/qemu/qemu_domain.c   |  4 +++
 src/qemu/qemu_process.c  |  3 ++
 src/qemu/qemu_validate.c |  2 +-
 5 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 6f9c707..5eb0225 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -27,6 +27,7 @@
 #include "viralloc.h"
 #include "virstring.h"
 #include "virlog.h"
+#include "virqemu.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -3438,3 +3439,73 @@ qemuBlockUpdateRelativeBacking(virDomainObjPtr vm,
 
     return 0;
 }
+
+int
+qemuBlockCreateTransientDisk(virStorageSourcePtr src,
+                             qemuDomainObjPrivatePtr priv)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virCommandPtr cmd = NULL;
+    g_autofree char *filename = NULL;
+    g_autofree char *dirname = NULL;
+    const char *qemuImgPath;
+    char *newpath;
+    int err = -1;
+
+    if ((src->format != VIR_STORAGE_FILE_QCOW2)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s", _("transient option supports qcow2"));
+        return -1;
+    }
+
+    if (!(qemuImgPath = qemuFindQemuImgBinary(priv->driver)))
+        return -1;
+
+    newpath = g_strdup_printf("%s.TRANSIENT", src->path);
+
+    if (virFileExists(newpath)) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _(" '%s' is already exists. Please remove it."), newpath);
+        goto cleanup;
+    }
+
+    if (!(cmd = virCommandNewArgList(qemuImgPath,
+                                     "create",
+                                     "-f",
+                                     "qcow2",
+                                     "-F",
+                                     "qcow2",
+                                     "-b",
+                                     NULL)))
+        goto cleanup;
+
+    virQEMUBuildBufferEscapeComma(&buf, src->path);
+    virCommandAddArgBuffer(cmd, &buf);
+
+    virQEMUBuildBufferEscapeComma(&buf, newpath);
+    virCommandAddArgBuffer(cmd, &buf);
+
+    if (virCommandRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    VIR_DEBUG("Original disk: %s Transient disk: %s", src->path, newpath);
+
+    g_free(src->path);
+    src->path = newpath;
+
+    err = 0;
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    virCommandFree(cmd);
+    if (err)
+        g_free(newpath);
+
+    return err;
+}
+
+void
+qemuBlockRemoveTransientDisk(virStorageSourcePtr src)
+{
+    VIR_DEBUG("unlink transient disk: %s ", src->path);
+    unlink(src->path);
+}
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 2ad2ce1..60c6898 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -266,3 +266,10 @@ int
 qemuBlockUpdateRelativeBacking(virDomainObjPtr vm,
                                virStorageSourcePtr src,
                                virStorageSourcePtr topsrc);
+
+int
+qemuBlockCreateTransientDisk(virStorageSourcePtr src,
+                             qemuDomainObjPrivatePtr priv);
+
+void
+qemuBlockRemoveTransientDisk(virStorageSourcePtr src);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d5e3d1a..9dbf73c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8301,6 +8301,10 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
 
     qemuDomainGetImageIds(cfg, vm, src, disksrc, &uid, &gid);
 
+    if (disk->transient)
+        if (qemuBlockCreateTransientDisk(src, vm->privateData) < 0)
+            return -1;
+
     if (virStorageFileGetMetadata(src, uid, gid, report_broken) < 0)
         return -1;
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 999e576..859ef82 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7597,6 +7597,9 @@ void qemuProcessStop(virQEMUDriverPtr driver,
             }
 
             qemuBlockRemoveImageMetadata(driver, vm, disk->dst, disk->src);
+
+            if (disk->transient)
+                qemuBlockRemoveTransientDisk(disk->src);
         }
     }
 
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 584d137..cdda6ac 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2098,7 +2098,7 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk,
         }
     }
 
-    if (disk->transient) {
+    if ((disk->transient) && (disk->src->format != VIR_STORAGE_FILE_QCOW2)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("transient disks not supported yet"));
         return -1;
-- 
2.27.0




More information about the libvir-list mailing list