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