[libvirt] [RFC PATCH 08/10] qemu: check backup destination before start

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Mon Nov 14 07:15:00 UTC 2016


If backup target is file then check it is not present or regular
empty file otherwise. If backup target is block device then
check it is present.
---

I decided to use switches instead of more compact if branches as in other
places so that the code will noticeably break when this function will
be called for storage types other then file or block.

 src/qemu/qemu_driver.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 17055b2..a606058 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20261,6 +20261,72 @@ qemuDomainSetGuestVcpus(virDomainPtr dom,
 }
 
 
+static int
+qemuDomainBackupPrepareDisk(virDomainBackupDiskDefPtr disk)
+{
+    int ret = -1;
+    struct stat st;
+    virStorageSourcePtr target = disk->target;
+
+    if (virStorageFileInit(target) < 0)
+        return -1;
+
+    if (virStorageFileStat(target, &st) < 0) {
+        if (errno != ENOENT) {
+            virReportSystemError(errno,
+                                 _("unable to stat target path '%s' for disk '%s'"),
+                                 target->path, disk->name);
+            goto cleanup;
+        }
+        switch (target->type) {
+        case VIR_STORAGE_TYPE_FILE:
+            break;
+        case VIR_STORAGE_TYPE_BLOCK:
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("missing target block device '%s' for disk '%s'"),
+                           target->path, disk->name);
+            goto cleanup;
+        default:
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("unexpected backup target type '%s' for disk '%s'"),
+                           virStorageTypeToString(target->type),
+                           disk->name);
+            goto cleanup;
+        }
+    } else {
+        switch (target->type) {
+        case VIR_STORAGE_TYPE_FILE:
+            if (!S_ISREG(st.st_mode) || st.st_size > 0) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("invalid existing target file '%s' for disk '%s'"),
+                               target->path, disk->name);
+                goto cleanup;
+            }
+            break;
+        case VIR_STORAGE_TYPE_BLOCK:
+            if (!S_ISBLK(st.st_mode)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("target file '%s' for disk '%s' is not a block device"),
+                               target->path, disk->name);
+                goto cleanup;
+            }
+            break;
+        default:
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("unexpected backup target type '%s' for disk '%s'"),
+                           virStorageTypeToString(target->type), disk->name);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+ cleanup:
+    virStorageFileDeinit(target);
+    return ret;
+}
+
+
 static virDomainBackupPtr
 qemuDomainBackupCreateXML(virDomainPtr domain,
                           const char *xmlDesc,
@@ -20336,6 +20402,9 @@ qemuDomainBackupCreateXML(virDomainPtr domain,
         if (qemuDomainDiskBlockJobIsActive(disk))
             goto cleanup;
 
+        if (qemuDomainBackupPrepareDisk(&def->disks[i]) < 0)
+            goto cleanup;
+
         if (qemuGetDriveSourceString(target, NULL, &path) < 0)
             goto cleanup;
 
-- 
1.8.3.1




More information about the libvir-list mailing list