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