diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0a45cdf5e3..b70f4498fc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2156,6 +2156,7 @@ virStorageSourceParseRBDColonString; virStorageSourcePoolDefFree; virStorageSourcePoolModeTypeFromString; virStorageSourcePoolModeTypeToString; +virStorageSourceUpdateBlockPhysicalSize; virStorageTypeFromString; virStorageTypeToString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 641abac917..9ffced3c7b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11823,8 +11823,16 @@ qemuDomainGetBlockInfo(virDomainPtr dom, info->allocation = entry->wr_highest_offset; } + if (entry->physical) { + info->physical = entry->physical; + } else { + if (virStorageSourceUpdateBlockPhysicalSize(disk->src, true) < 0) + goto endjob; + + info->physical = disk->src->physical; + } + info->capacity = entry->capacity; - info->physical = entry->physical; ret = 0; @@ -19270,9 +19278,15 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, if (entry->capacity) QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, "capacity", entry->capacity); - if (entry->physical) + if (entry->physical) { QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, "physical", entry->physical); + } else { + if (virStorageSourceUpdateBlockPhysicalSize(src, false) == 0) { + QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, + "physical", src->physical); + } + } ret = 0; cleanup: diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 6c3017cef9..2aa1d90d65 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2587,6 +2587,45 @@ virStorageSourceNewFromBacking(virStorageSourcePtr parent) } +/** + * @src: disk source definiton structure + * @report: report libvirt errors if set to true + * + * Updates src->physical for block devices since qemu doesn't report the current + * size correctly for them. Returns 0 on success, -1 on error. + */ +int +virStorageSourceUpdateBlockPhysicalSize(virStorageSourcePtr src, + bool report) +{ + int fd = -1; + off_t end; + int ret = -1; + + if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_BLOCK) + return 0; + + if ((fd = open(src->path, O_RDONLY)) < 0) { + if (report) + virReportSystemError(errno, _("failed to open block device '%s'"), + src->path); + return -1; + } + + if ((end = lseek(fd, 0, SEEK_END)) == (off_t) -1) { + if (report) + virReportSystemError(errno, + _("failed to seek to end of '%s'"), src->path); + } else { + src->physical = end; + ret = 0; + } + + VIR_FORCE_CLOSE(fd); + return ret; +} + + static char * virStorageFileCanonicalizeFormatPath(char **components, size_t ncomponents, diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index aa17a00e54..b98fe25871 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -362,6 +362,8 @@ bool virStorageSourceIsLocalStorage(virStorageSourcePtr src); bool virStorageSourceIsEmpty(virStorageSourcePtr src); void virStorageSourceFree(virStorageSourcePtr def); void virStorageSourceBackingStoreClear(virStorageSourcePtr def); +int virStorageSourceUpdateBlockPhysicalSize(virStorageSourcePtr src, + bool report); virStorageSourcePtr virStorageSourceNewFromBacking(virStorageSourcePtr parent); virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src, bool backingChain)