[libvirt] [PATCH v3 RESEND 08/12] qemu_domain: Introduce qemuDomainGetDiskBlockInfo
Jiri Denemark
jdenemar at redhat.com
Wed Feb 20 13:44:33 UTC 2013
On Mon, Feb 18, 2013 at 15:38:41 +0100, Michal Privoznik wrote:
> This is just digging out important implementation from qemu
> driver's qemuDomainGetDiskBlockInfo() API as this functionality
> is going to be required in the next patch.
> ---
> src/qemu/qemu_domain.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_domain.h | 4 ++
> src/qemu/qemu_driver.c | 124 +++--------------------------------------------
> 3 files changed, 138 insertions(+), 117 deletions(-)
>
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 482f64a..8df2739 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -40,6 +40,9 @@
>
> #include <sys/time.h>
> #include <fcntl.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
>
> #include <libxml/xpathInternals.h>
>
> @@ -1959,3 +1962,127 @@ cleanup:
> virObjectUnref(cfg);
> return ret;
> }
> +
> +int
> +qemuDomainGetDiskBlockInfo(virQEMUDriverPtr driver,
> + virDomainObjPtr vm,
> + virDomainDiskDefPtr disk,
> + virDomainBlockInfoPtr info)
> +{
> +
> + int ret = -1;
> + virStorageFileMetadata *meta = NULL;
> + virQEMUDriverConfigPtr cfg = NULL;
> + int format;
> + struct stat sb;
> + int fd = -1;
> + off_t end;
> + const char *path;
> +
> + if (!disk->src) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("disk %s does not currently have a source assigned"),
> + disk->dst);
> + goto cleanup;
> + }
> + path = disk->src;
> + cfg = virQEMUDriverGetConfig(driver);
> +
> + /* The path is correct, now try to open it and get its size. */
> + if ((fd = open(path, O_RDONLY)) < 0) {
This should really check for -1 only, which is what the original code
did.
> + virReportSystemError(errno, _("failed to open path '%s'"), path);
> + goto cleanup;
> + }
> +
> + /* Probe for magic formats */
> + if (disk->format) {
> + format = disk->format;
> + } else {
> + if (cfg->allowDiskFormatProbing) {
> + if ((format = virStorageFileProbeFormat(path,
> + cfg->user,
> + cfg->group)) < 0)
> + goto cleanup;
> + } else {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("no disk format for %s and probing is disabled"),
> + path);
> + goto cleanup;
> + }
> + }
> +
> + if (!(meta = virStorageFileGetMetadataFromFD(path, fd, format)))
> + goto cleanup;
> +
> + /* Get info for normal formats */
> + if (fstat(fd, &sb) < 0) {
> + virReportSystemError(errno, _("cannot stat file '%s'"), path);
> + goto cleanup;
> + }
> +
> + if (S_ISREG(sb.st_mode)) {
> +#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 running & not using raw
> + disk format and on a block device, then query
> + highest allocated extent from QEMU */
> + if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
> + format != VIR_STORAGE_FILE_RAW &&
> + S_ISBLK(sb.st_mode) &&
> + virDomainObjIsActive(vm)) {
> + qemuDomainObjPrivatePtr priv = vm->privateData;
> +
> + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
> + goto cleanup;
> +
> + if (virDomainObjIsActive(vm)) {
> + qemuDomainObjEnterMonitor(driver, vm);
> + ret = qemuMonitorGetBlockExtent(priv->mon,
> + disk->info.alias,
> + &info->allocation);
> + qemuDomainObjExitMonitor(driver, vm);
> + } else {
> + ret = 0;
> + }
> +
> + if (qemuDomainObjEndJob(driver, vm) == 0)
> + vm = NULL;
As already found by John, this would not work. You either need to move
setting up the job outside of this function or pass a reference to vm
inside.
> + } else {
> + ret = 0;
> + }
> +
> +cleanup:
> + VIR_FORCE_CLOSE(fd);
> + virStorageFileFreeMetadata(meta);
> + virObjectUnref(cfg);
> + return ret;
> +}
...
Jirka
More information about the libvir-list
mailing list