[libvirt] [PATCH v2 5/7] qemu: refactor blockinfo data gathering

Eric Blake eblake at redhat.com
Tue Nov 18 13:31:51 UTC 2014


Create a helper function that can be reused to implement the
new VIR_DOMAIN_XML_BLOCK_INFO flag.

* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Split guts...
(qemuStorageLimitsRefresh): ...into new helper function.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 src/qemu/qemu_driver.c | 287 ++++++++++++++++++++++++++-----------------------
 1 file changed, 151 insertions(+), 136 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index aa24658..7b1431b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6179,6 +6179,151 @@ qemuDomainObjRestore(virConnectPtr conn,
 }


+/* Refresh the capacity and allocation limits of a given storage
+ * source.  Assumes that the caller has already obtained a domain job.
+ * Set *activeFail to true if data cannot be obtained because a
+ * transient guest is no longer active.  */
+static int
+qemuStorageLimitsRefresh(virQEMUDriverPtr driver, virQEMUDriverConfigPtr cfg,
+                         virDomainObjPtr vm, virDomainDiskDefPtr disk,
+                         const char *path, bool *activeFail)
+{
+    int ret = -1;
+    int fd = -1;
+    off_t end;
+    virStorageSourcePtr meta = NULL;
+    struct stat sb;
+    int format;
+    char *buf = NULL;
+    ssize_t len;
+
+    if (virStorageSourceIsLocalStorage(disk->src)) {
+        if (!disk->src->path) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("disk '%s' does not currently have a source assigned"),
+                           path);
+            goto cleanup;
+        }
+
+        if ((fd = qemuOpenFile(driver, vm, disk->src->path, O_RDONLY,
+                               NULL, NULL)) == -1)
+            goto cleanup;
+
+        if (fstat(fd, &sb) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot stat file '%s'"), disk->src->path);
+            goto cleanup;
+        }
+
+        if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
+            virReportSystemError(errno, _("cannot read header '%s'"),
+                                 disk->src->path);
+            goto cleanup;
+        }
+    } else {
+        if (virStorageFileInitAs(disk->src, cfg->user, cfg->group) < 0)
+            goto cleanup;
+
+        if ((len = virStorageFileReadHeader(disk->src, VIR_STORAGE_MAX_HEADER,
+                                            &buf)) < 0)
+            goto cleanup;
+
+        if (virStorageFileStat(disk->src, &sb) < 0) {
+            virReportSystemError(errno, _("failed to stat remote file '%s'"),
+                                 NULLSTR(disk->src->path));
+            goto cleanup;
+        }
+    }
+
+    /* Probe for magic formats */
+    if (virDomainDiskGetFormat(disk)) {
+        format = virDomainDiskGetFormat(disk);
+    } else {
+        if (!cfg->allowDiskFormatProbing) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("no disk format for %s and probing is disabled"),
+                           path);
+            goto cleanup;
+        }
+
+        if ((format = virStorageFileProbeFormatFromBuf(disk->src->path,
+                                                       buf, len)) < 0)
+            goto cleanup;
+    }
+
+    if (!(meta = virStorageFileGetMetadataFromBuf(disk->src->path, buf, len,
+                                                  format, NULL)))
+        goto cleanup;
+
+    /* Get info for normal formats */
+    if (S_ISREG(sb.st_mode) || fd == -1) {
+#ifndef WIN32
+        disk->src->physical = (unsigned long long)sb.st_blocks *
+            (unsigned long long)DEV_BSIZE;
+#else
+        disk->src->physical = sb.st_size;
+#endif
+        /* Regular files may be sparse, so logical size (capacity) is not same
+         * as actual physical above
+         */
+        disk->src->capacity = sb.st_size;
+    } else {
+        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
+         * be 64 bits on all platforms.
+         */
+        end = lseek(fd, 0, SEEK_END);
+        if (end == (off_t)-1) {
+            virReportSystemError(errno,
+                                 _("failed to seek to end of %s"), path);
+            goto cleanup;
+        }
+        disk->src->physical = end;
+        disk->src->capacity = end;
+    }
+
+    /* If the file we probed has a capacity set, then override
+     * what we calculated from file/block extents */
+    if (meta->capacity)
+        disk->src->capacity = meta->capacity;
+
+    /* Set default value .. */
+    disk->src->allocation = disk->src->physical;
+
+    /* ..but if guest is not using raw disk format and on a block device,
+     * then query highest allocated extent from QEMU
+     */
+    if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_BLOCK &&
+        format != VIR_STORAGE_FILE_RAW &&
+        S_ISBLK(sb.st_mode)) {
+        qemuDomainObjPrivatePtr priv = vm->privateData;
+
+        /* If the guest is not running, then success/failure return
+         * depends on whether domain is persistent
+         */
+        if (!virDomainObjIsActive(vm)) {
+            *activeFail = true;
+            ret = 0;
+            goto cleanup;
+        }
+
+        qemuDomainObjEnterMonitor(driver, vm);
+        ret = qemuMonitorGetBlockExtent(priv->mon,
+                                        disk->info.alias,
+                                        &disk->src->allocation);
+        qemuDomainObjExitMonitor(driver, vm);
+
+    } else {
+        ret = 0;
+    }
+ cleanup:
+    VIR_FREE(buf);
+    virStorageSourceFree(meta);
+    VIR_FORCE_CLOSE(fd);
+    virStorageFileDeinit(disk->src);
+    return ret;
+}
+
+
 static char *qemuDomainGetXMLDesc(virDomainPtr dom,
                                   unsigned int flags)
 {
@@ -10941,17 +11086,10 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     int ret = -1;
-    int fd = -1;
-    off_t end;
-    virStorageSourcePtr meta = NULL;
     virDomainDiskDefPtr disk = NULL;
-    struct stat sb;
     int idx;
-    int format;
-    int activeFail = false;
+    bool activeFail = false;
     virQEMUDriverConfigPtr cfg = NULL;
-    char *buf = NULL;
-    ssize_t len;

     virCheckFlags(0, -1);

@@ -10985,141 +11123,18 @@ qemuDomainGetBlockInfo(virDomainPtr dom,

     disk = vm->def->disks[idx];

-    if (virStorageSourceIsLocalStorage(disk->src)) {
-        if (!disk->src->path) {
-            virReportError(VIR_ERR_INVALID_ARG,
-                           _("disk '%s' does not currently have a source assigned"),
-                           path);
-            goto endjob;
-        }
-
-        if ((fd = qemuOpenFile(driver, vm, disk->src->path, O_RDONLY,
-                               NULL, NULL)) == -1)
-            goto endjob;
-
-        if (fstat(fd, &sb) < 0) {
-            virReportSystemError(errno,
-                                 _("cannot stat file '%s'"), disk->src->path);
-            goto endjob;
-        }
-
-        if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
-            virReportSystemError(errno, _("cannot read header '%s'"),
-                                 disk->src->path);
-            goto endjob;
-        }
-    } else {
-        if (virStorageFileInitAs(disk->src, cfg->user, cfg->group) < 0)
-            goto endjob;
-
-        if ((len = virStorageFileReadHeader(disk->src, VIR_STORAGE_MAX_HEADER,
-                                            &buf)) < 0)
-            goto endjob;
-
-        if (virStorageFileStat(disk->src, &sb) < 0) {
-            virReportSystemError(errno, _("failed to stat remote file '%s'"),
-                                 NULLSTR(disk->src->path));
-            goto endjob;
-        }
-    }
-
-    /* Probe for magic formats */
-    if (virDomainDiskGetFormat(disk)) {
-        format = virDomainDiskGetFormat(disk);
-    } else {
-        if (!cfg->allowDiskFormatProbing) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("no disk format for %s and probing is disabled"),
-                           path);
-            goto endjob;
-        }
-
-        if ((format = virStorageFileProbeFormatFromBuf(disk->src->path,
-                                                       buf, len)) < 0)
-            goto endjob;
-    }
-
-    if (!(meta = virStorageFileGetMetadataFromBuf(disk->src->path, buf, len,
-                                                  format, NULL)))
+    if ((ret = qemuStorageLimitsRefresh(driver, cfg, vm, disk, path,
+                                        &activeFail)) < 0)
         goto endjob;

-    /* Get info for normal formats */
-    if (S_ISREG(sb.st_mode) || fd == -1) {
-#ifndef WIN32
-        disk->src->physical = (unsigned long long)sb.st_blocks *
-            (unsigned long long)DEV_BSIZE;
-#else
-        disk->src->physical = sb.st_size;
-#endif
-        /* Regular files may be sparse, so logical size (capacity) is not same
-         * as actual physical above
-         */
-        disk->src->capacity = sb.st_size;
-    } else {
-        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
-         * be 64 bits on all platforms.
-         */
-        end = lseek(fd, 0, SEEK_END);
-        if (end == (off_t)-1) {
-            virReportSystemError(errno,
-                                 _("failed to seek to end of %s"), path);
-            goto endjob;
-        }
-        disk->src->physical = end;
-        disk->src->capacity = end;
-    }
-
-    /* If the file we probed has a capacity set, then override
-     * what we calculated from file/block extents */
-    if (meta->capacity)
-        disk->src->capacity = meta->capacity;
-
-    /* Set default value .. */
-    disk->src->allocation = disk->src->physical;
-
-    /* ..but if guest is not using raw disk format and on a block device,
-     * then query highest allocated extent from QEMU
-     */
-    if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_BLOCK &&
-        format != VIR_STORAGE_FILE_RAW &&
-        S_ISBLK(sb.st_mode)) {
-        qemuDomainObjPrivatePtr priv = vm->privateData;
-
-        /* If the guest is not running, then success/failure return
-         * depends on whether domain is persistent
-         */
-        if (!virDomainObjIsActive(vm)) {
-            activeFail = true;
-            ret = 0;
-            goto endjob;
-        }
-
-        qemuDomainObjEnterMonitor(driver, vm);
-        ret = qemuMonitorGetBlockExtent(priv->mon,
-                                        disk->info.alias,
-                                        &disk->src->allocation);
-        qemuDomainObjExitMonitor(driver, vm);
-
-    } else {
-        ret = 0;
-    }
-
-    if (ret == 0) {
-        info->capacity = disk->src->capacity;
-        info->allocation = disk->src->allocation;
-        info->physical = disk->src->physical;
-    }
+    info->capacity = disk->src->capacity;
+    info->allocation = disk->src->allocation;
+    info->physical = disk->src->physical;

  endjob:
     if (!qemuDomainObjEndJob(driver, vm))
         vm = NULL;
  cleanup:
-    VIR_FREE(buf);
-    virStorageSourceFree(meta);
-    VIR_FORCE_CLOSE(fd);
-    if (disk)
-        virStorageFileDeinit(disk->src);
-
     /* If we failed to get data from a domain because it's inactive and
      * it's not a persistent domain, then force failure.
      */
-- 
1.9.3




More information about the libvir-list mailing list