/** virDomainBlockInfo:
*
* This struct provides information about the size of a block device
- * backing store
+ * backing store.
*
* Examples:
*
* * 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
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,
/* 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) {
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,
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 &&