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(a)redhat.com>
---
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