diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index ae2c49c75a7823ff4b38a26e2671b02990eb8701..baef32d809b958e71fd503986072e92809439f2a 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1356,7 +1356,7 @@ int virDomainBlockResize (virDomainPtr dom, /** virDomainBlockInfo: * * This struct provides information about the size of a block device - * backing store + * backing store. * * Examples: * @@ -1364,13 +1364,13 @@ int virDomainBlockResize (virDomainPtr dom, * * capacity, allocation, physical: All the same * * - Sparse raw file in filesystem: - * * capacity: logical size of the file - * * allocation, physical: number of blocks allocated to file + * * capacity, size: logical size of the file + * * allocation: disk space occupied by file * * - qcow2 file in filesystem * * capacity: logical size from qcow2 header - * * allocation, physical: logical size of the file / - * highest qcow extent (identical) + * * allocation: disk space occupied by file + * * physical: reported size of qcow2 file * * - qcow2 file in a block device * * capacity: logical size from qcow2 header @@ -1380,9 +1380,16 @@ int virDomainBlockResize (virDomainPtr dom, typedef struct _virDomainBlockInfo virDomainBlockInfo; typedef virDomainBlockInfo *virDomainBlockInfoPtr; struct _virDomainBlockInfo { - unsigned long long capacity; /* logical size in bytes of the block device backing image */ - unsigned long long allocation; /* highest allocated extent in bytes of the block device backing image */ - unsigned long long physical; /* physical size in bytes of the container of the backing image */ + unsigned long long capacity; /* logical size in bytes of the + * image (how much storage the + * guest will see) */ + unsigned long long allocation; /* host storage in bytes occupied + * by the image (such as highest + * allocated extent if there are no + * holes, similar to 'du') */ + unsigned long long physical; /* host physical size in bytes of + * the image container (last + * offset, similar to 'ls')*/ }; int virDomainGetBlockInfo(virDomainPtr dom, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3d81a5b3feb23fc75e32891064f1dd4ee73aef44..f7373a5a6872d33bf978d527e9f7e77f6c06f4b1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11118,18 +11118,21 @@ qemuDomainGetBlockInfo(virDomainPtr dom, /* Get info for normal formats */ if (S_ISREG(sb.st_mode) || fd == -1) { #ifndef WIN32 - src->physical = (unsigned long long)sb.st_blocks * + src->allocation = (unsigned long long)sb.st_blocks * (unsigned long long)DEV_BSIZE; #else - src->physical = sb.st_size; + src->allocation = sb.st_size; #endif - /* Regular files may be sparse, so logical size (capacity) is not same - * as actual physical above - */ - src->capacity = sb.st_size; + /* Allocation tracks when the file is sparse, physical is the + * last offset of the file. */ + src->physical = sb.st_size; } else { - /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should - * be 64 bits on all platforms. + /* NB. Because we configure with AC_SYS_LARGEFILE, off_t + * should be 64 bits on all platforms. For block devices, we + * have to seek (safe even if someone else is writing) to + * determine physical size, and assume that allocation is the + * same as physical (but can refine that assumption later if + * qemu is still running). */ end = lseek(fd, 0, SEEK_END); if (end == (off_t)-1) { @@ -11138,12 +11141,12 @@ qemuDomainGetBlockInfo(virDomainPtr dom, goto endjob; } src->physical = end; - src->capacity = end; + src->allocation = end; } - /* If the file we probed has a capacity set, then override - * what we calculated from file/block extents */ - /* Probe for magic formats */ + /* Raw files: capacity is physical size. For all other files: if + * the metadata has a capacity, use that, otherwise fall back to + * physical size. */ if (!(format = src->format)) { if (!cfg->allowDiskFormatProbing) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -11159,13 +11162,15 @@ qemuDomainGetBlockInfo(virDomainPtr dom, if (!(meta = virStorageFileGetMetadataFromBuf(src->path, buf, len, format, NULL))) goto endjob; - if (meta->capacity) - src->capacity = meta->capacity; - - /* Set default value .. */ - src->allocation = src->physical; + if (format == VIR_STORAGE_FILE_RAW) + src->capacity = src->physical; + else if ((meta = virStorageFileGetMetadataFromBuf(src->path, buf, + len, format, NULL))) + src->capacity = meta->capacity ? meta->capacity : src->physical; + else + goto endjob; - /* ..but if guest is not using raw disk format and on a block device, + /* If guest is not using raw disk format and on a block device, * then query highest allocated extent from QEMU */ if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK &&