Again, this is a pure code movement. The function internals are going to be needed later when determining the disk capacity. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/qemu/qemu_domain.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 6 ++ src/qemu/qemu_driver.c | 160 +-------------------------------------------- 3 files changed, 179 insertions(+), 159 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e500fb3..0484df5 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2957,3 +2957,175 @@ qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid, path); goto cleanup; } + + +int +qemuDomainGetBlockInfoImpl(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDiskDefPtr disk, + virDomainBlockInfoPtr info, + const char *path) +{ + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + int ret = -1; + int fd = -1; + struct stat sb; + ssize_t len; + char *buf = NULL; + int format; + virStorageSourcePtr meta = NULL; + off_t end; + char *alias = NULL; + bool activeFail = false; + + 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 + info->physical = (unsigned long long)sb.st_blocks * + (unsigned long long)DEV_BSIZE; +#else + info->physical = sb.st_size; +#endif + /* Regular files may be sparse, so logical size (capacity) is not same + * as actual physical above + */ + info->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; + } + info->physical = end; + info->capacity = end; + } + + /* If the file we probed has a capacity set, then override + * what we calculated from file/block extents */ + if (meta->capacity) + info->capacity = meta->capacity; + + /* Set default value .. */ + info->allocation = info->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; + } + + if (VIR_STRDUP(alias, disk->info.alias) < 0) + goto cleanup; + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) + goto cleanup; + + if (virDomainObjIsActive(vm)) { + qemuDomainObjEnterMonitor(driver, vm); + ret = qemuMonitorGetBlockExtent(priv->mon, + alias, + &info->allocation); + qemuDomainObjExitMonitor(driver, vm); + } else { + activeFail = true; + ret = 0; + } + + if (!qemuDomainObjEndJob(driver, vm)) + vm = NULL; + } else { + ret = 0; + } + + cleanup: + VIR_FREE(buf); + VIR_FREE(alias); + 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. + */ + if (activeFail && vm && !vm->persistent) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain is not running")); + ret = -1; + } + virObjectUnref(cfg); + return ret; +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 5f36892..d3377c5 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -424,4 +424,10 @@ int qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid, const char *path, int oflags, bool *needUnlink, bool *bypassSecurityDriver); +int +qemuDomainGetBlockInfoImpl(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDiskDefPtr disk, + virDomainBlockInfoPtr info, + const char *path); #endif /* __QEMU_DOMAIN_H__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 561fa6c..71b7e81 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10833,26 +10833,14 @@ 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; - bool activeFail = false; - virQEMUDriverConfigPtr cfg = NULL; - char *alias = NULL; - 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; @@ -10870,156 +10858,10 @@ 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 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 - info->physical = (unsigned long long)sb.st_blocks * - (unsigned long long)DEV_BSIZE; -#else - info->physical = sb.st_size; -#endif - /* Regular files may be sparse, so logical size (capacity) is not same - * as actual physical above - */ - info->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; - } - info->physical = end; - info->capacity = end; - } - - /* If the file we probed has a capacity set, then override - * what we calculated from file/block extents */ - if (meta->capacity) - info->capacity = meta->capacity; - - /* Set default value .. */ - info->allocation = info->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; - } - - if (VIR_STRDUP(alias, disk->info.alias) < 0) - goto cleanup; - - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) - goto cleanup; - - if (virDomainObjIsActive(vm)) { - qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorGetBlockExtent(priv->mon, - alias, - &info->allocation); - qemuDomainObjExitMonitor(driver, vm); - } else { - activeFail = true; - ret = 0; - } - - if (!qemuDomainObjEndJob(driver, vm)) - vm = NULL; - } else { - ret = 0; - } + ret = qemuDomainGetBlockInfoImpl(driver, vm, disk, info, path); cleanup: - VIR_FREE(buf); - VIR_FREE(alias); - 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. - */ - if (activeFail && vm && !vm->persistent) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("domain is not running")); - ret = -1; - } virObjectUnlock(vm); - virObjectUnref(cfg); return ret; } -- 2.0.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list