[libvirt] [PATCH 05/12] qemu: refactor blockinfo data gathering

Eric Blake eblake at redhat.com
Sat Dec 6 08:14:13 UTC 2014


Create a helper function that can be reused for gathering block
info from virDomainListGetStats.

* 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 | 196 ++++++++++++++++++++++++++-----------------------
 1 file changed, 105 insertions(+), 91 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e873362..1e254bc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10981,59 +10981,25 @@ qemuDomainMemoryPeek(virDomainPtr dom,
 }


+/* 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
-qemuDomainGetBlockInfo(virDomainPtr dom,
-                       const char *path,
-                       virDomainBlockInfoPtr info,
-                       unsigned int flags)
+qemuStorageLimitsRefresh(virQEMUDriverPtr driver, virQEMUDriverConfigPtr cfg,
+                         virDomainObjPtr vm, virDomainDiskDefPtr disk,
+                         virStorageSourcePtr src, const char *path,
+                         bool *activeFail)
 {
-    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;
-    bool activeFail = false;
-    virQEMUDriverConfigPtr cfg = NULL;
+    int format = src->format;
     char *buf = NULL;
     ssize_t len;

-    virCheckFlags(0, -1);
-
-    if (!(vm = qemuDomObjFromDomain(dom)))
-        return -1;
-
-    cfg = virQEMUDriverGetConfig(driver);
-
-    if (virDomainGetBlockInfoEnsureACL(dom->conn, vm->def) < 0)
-        goto cleanup;
-
-    if (!path || path[0] == '\0') {
-        virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path"));
-        goto cleanup;
-    }
-
-    /* Technically, we only need a job if we are going to query the
-     * monitor, which is only for active domains that are using
-     * non-raw block devices.  But it is easier to share code if we
-     * always grab a job; furthermore, grabbing the job ensures that
-     * hot-plug won't change disk behind our backs.  */
-    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
-        goto cleanup;
-
-    /* Check the path belongs to this domain. */
-    if ((idx = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("invalid path %s not assigned to domain"), path);
-        goto endjob;
-    }
-
-    disk = vm->def->disks[idx];
-
     /* FIXME: For an offline domain, we always want to check current
      * on-disk statistics (as users have been known to change offline
      * images behind our backs).  For a running domain, however, it
@@ -11054,76 +11020,74 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
      * punching holes), and physical size of a non-raw file can
      * change.
      */
-    if (virStorageSourceIsLocalStorage(disk->src)) {
-        if (!disk->src->path) {
+    if (virStorageSourceIsLocalStorage(src)) {
+        if (!src->path) {
             virReportError(VIR_ERR_INVALID_ARG,
                            _("disk '%s' does not currently have a source assigned"),
                            path);
-            goto endjob;
+            goto cleanup;
         }

-        if ((fd = qemuOpenFile(driver, vm, disk->src->path, O_RDONLY,
+        if ((fd = qemuOpenFile(driver, vm, src->path, O_RDONLY,
                                NULL, NULL)) == -1)
-            goto endjob;
+            goto cleanup;

         if (fstat(fd, &sb) < 0) {
             virReportSystemError(errno,
-                                 _("cannot stat file '%s'"), disk->src->path);
-            goto endjob;
+                                 _("cannot stat file '%s'"), src->path);
+            goto cleanup;
         }

         if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
             virReportSystemError(errno, _("cannot read header '%s'"),
-                                 disk->src->path);
-            goto endjob;
+                                 src->path);
+            goto cleanup;
         }
     } else {
-        if (virStorageFileInitAs(disk->src, cfg->user, cfg->group) < 0)
-            goto endjob;
+        if (virStorageFileInitAs(src, cfg->user, cfg->group) < 0)
+            goto cleanup;

-        if ((len = virStorageFileReadHeader(disk->src, VIR_STORAGE_MAX_HEADER,
+        if ((len = virStorageFileReadHeader(src, VIR_STORAGE_MAX_HEADER,
                                             &buf)) < 0)
-            goto endjob;
+            goto cleanup;

-        if (virStorageFileStat(disk->src, &sb) < 0) {
+        if (virStorageFileStat(src, &sb) < 0) {
             virReportSystemError(errno, _("failed to stat remote file '%s'"),
-                                 NULLSTR(disk->src->path));
-            goto endjob;
+                                 NULLSTR(src->path));
+            goto cleanup;
         }
     }

     /* Probe for magic formats */
-    if (virDomainDiskGetFormat(disk)) {
-        format = virDomainDiskGetFormat(disk);
-    } else {
+    if (!format) {
         if (!cfg->allowDiskFormatProbing) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("no disk format for %s and probing is disabled"),
                            path);
-            goto endjob;
+            goto cleanup;
         }

-        if ((format = virStorageFileProbeFormatFromBuf(disk->src->path,
+        if ((format = virStorageFileProbeFormatFromBuf(src->path,
                                                        buf, len)) < 0)
-            goto endjob;
+            goto cleanup;
     }

-    if (!(meta = virStorageFileGetMetadataFromBuf(disk->src->path, buf, len,
+    if (!(meta = virStorageFileGetMetadataFromBuf(src->path, buf, len,
                                                   format, NULL)))
-        goto endjob;
+        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 *
+        src->physical = (unsigned long long)sb.st_blocks *
             (unsigned long long)DEV_BSIZE;
 #else
-        disk->src->physical = sb.st_size;
+        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;
+        src->capacity = sb.st_size;
     } else {
         /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
          * be 64 bits on all platforms.
@@ -11132,24 +11096,24 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
         if (end == (off_t)-1) {
             virReportSystemError(errno,
                                  _("failed to seek to end of %s"), path);
-            goto endjob;
+            goto cleanup;
         }
-        disk->src->physical = end;
-        disk->src->capacity = end;
+        src->physical = end;
+        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;
+        src->capacity = meta->capacity;

     /* Set default value .. */
-    disk->src->allocation = disk->src->physical;
+    src->allocation = 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 &&
+    if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK &&
         format != VIR_STORAGE_FILE_RAW &&
         S_ISBLK(sb.st_mode)) {
         qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -11158,37 +11122,87 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
          * depends on whether domain is persistent
          */
         if (!virDomainObjIsActive(vm)) {
-            activeFail = true;
+            *activeFail = true;
             ret = 0;
-            goto endjob;
+            goto cleanup;
         }

         qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorGetBlockExtent(priv->mon,
                                         disk->info.alias,
-                                        &disk->src->allocation);
+                                        &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;
-    }
-
- endjob:
-    if (!qemuDomainObjEndJob(driver, vm))
-        vm = NULL;
  cleanup:
     VIR_FREE(buf);
     virStorageSourceFree(meta);
     VIR_FORCE_CLOSE(fd);
-    if (disk)
-        virStorageFileDeinit(disk->src);
+    virStorageFileDeinit(src);
+    return ret;
+}

+
+static int
+qemuDomainGetBlockInfo(virDomainPtr dom,
+                       const char *path,
+                       virDomainBlockInfoPtr info,
+                       unsigned int flags)
+{
+    virQEMUDriverPtr driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+    virDomainDiskDefPtr disk = NULL;
+    int idx;
+    bool activeFail = false;
+    virQEMUDriverConfigPtr cfg = NULL;
+
+    virCheckFlags(0, -1);
+
+    if (!(vm = qemuDomObjFromDomain(dom)))
+        return -1;
+
+    cfg = virQEMUDriverGetConfig(driver);
+
+    if (virDomainGetBlockInfoEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (!path || path[0] == '\0') {
+        virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path"));
+        goto cleanup;
+    }
+
+    /* Technically, we only need a job if we are going to query the
+     * monitor, which is only for active domains that are using
+     * non-raw block devices.  But it is easier to share code if we
+     * always grab a job; furthermore, grabbing the job ensures that
+     * hot-plug won't change disk behind our backs.  */
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+        goto cleanup;
+
+    /* Check the path belongs to this domain. */
+    if ((idx = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("invalid path %s not assigned to domain"), path);
+        goto endjob;
+    }
+
+    disk = vm->def->disks[idx];
+
+    if ((ret = qemuStorageLimitsRefresh(driver, cfg, vm, disk, disk->src, path,
+                                        &activeFail)) < 0)
+        goto endjob;
+
+    info->capacity = disk->src->capacity;
+    info->allocation = disk->src->allocation;
+    info->physical = disk->src->physical;
+
+ endjob:
+    if (!qemuDomainObjEndJob(driver, vm))
+        vm = NULL;
+ cleanup:
     /* 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