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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list