From: Peter Krempa Date: Mon, 7 Jul 2014 10:56:23 +0000 (+0200) Subject: qemu: refactor qemuDomainGetBlockInfo to work with remote storage X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=3ea661deeabadc3c114dfb6f662b9fd17d714a01;p=people%2Fliuw%2Flibxenctrl-split%2Flibvirt.git qemu: refactor qemuDomainGetBlockInfo to work with remote storage The qemu block info function relied on working with local storage. Break this assumption by adding support for remote volumes. Unfortunately we still need to take a hybrid approach as some of the operations require a filedescriptor. Previously you'd get: $ virsh domblkinfo gl vda error: cannot stat file '/img10': Bad file descriptor Now you get some stats: $ virsh domblkinfo gl vda Capacity: 10485760 Allocation: 197120 Physical: 197120 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1110198 --- diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 18d5f28c4..6d7bf4195 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1910,6 +1910,7 @@ virStorageFileGetSCSIKey; virStorageFileIsClusterFS; virStorageFileParseChainIndex; virStorageFileProbeFormat; +virStorageFileProbeFormatFromBuf; virStorageFileResize; virStorageIsFile; virStorageNetHostDefClear; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index fe76d5568..23f3f089a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10334,11 +10334,13 @@ qemuDomainGetBlockInfo(virDomainPtr dom, int activeFail = false; virQEMUDriverConfigPtr cfg = NULL; char *alias = NULL; + char *buf = NULL; + ssize_t len; virCheckFlags(0, -1); if (!(vm = qemuDomObjFromDomain(dom))) - goto cleanup; + return -1; cfg = virQEMUDriverGetConfig(driver); @@ -10346,8 +10348,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom, goto cleanup; if (!path || path[0] == '\0') { - virReportError(VIR_ERR_INVALID_ARG, - "%s", _("NULL or empty path")); + virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path")); goto cleanup; } @@ -10357,48 +10358,68 @@ qemuDomainGetBlockInfo(virDomainPtr dom, _("invalid path %s not assigned to domain"), path); goto cleanup; } + disk = vm->def->disks[idx]; - path = virDomainDiskGetSource(disk); - if (!path) { - virReportError(VIR_ERR_INVALID_ARG, - _("disk %s does not currently have a source assigned"), - path); - goto cleanup; - } - /* The path is correct, now try to open it and get its size. */ - fd = qemuOpenFile(driver, vm, path, O_RDONLY, NULL, NULL); - if (fd == -1) - goto cleanup; + 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, 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) { - if ((format = virStorageFileProbeFormat(path, - cfg->user, - cfg->group)) < 0) - goto cleanup; - } 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 = virStorageFileGetMetadataFromFD(path, fd, format, NULL))) + if (!(meta = virStorageFileGetMetadataFromBuf(disk->src->path, buf, len, + format, NULL))) 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)) { + if (S_ISREG(sb.st_mode) || fd == -1) { #ifndef WIN32 info->physical = (unsigned long long)sb.st_blocks * (unsigned long long)DEV_BSIZE; @@ -10434,7 +10455,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom, /* ..but if guest is not using raw disk format and on a block device, * then query highest allocated extent from QEMU */ - if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_BLOCK && + if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_BLOCK && format != VIR_STORAGE_FILE_RAW && S_ISBLK(sb.st_mode)) { qemuDomainObjPrivatePtr priv = vm->privateData; @@ -10475,6 +10496,8 @@ qemuDomainGetBlockInfo(virDomainPtr dom, 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. @@ -10484,8 +10507,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom, _("domain is not running")); ret = -1; } - if (vm) - virObjectUnlock(vm); + virObjectUnlock(vm); virObjectUnref(cfg); return ret; } diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 0b8715d04..466da0ae9 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -682,7 +682,7 @@ virStorageIsRelative(const char *backing) } -static int +int virStorageFileProbeFormatFromBuf(const char *path, char *buf, size_t buflen) diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 89ecc1e18..18d3a753b 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -276,6 +276,9 @@ struct _virStorageSource { # endif int virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid); +int virStorageFileProbeFormatFromBuf(const char *path, + char *buf, + size_t buflen); int virStorageFileGetMetadataInternal(virStorageSourcePtr meta, char *buf,