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(a)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