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