block: add bdrv_get_allocated_file_size() operation
qemu-img.c wants to count allocated file size of image. Previously it counts a single bs->file by 'stat' or Window API. As VMDK introduces multiple file support, the operation becomes format specific with platform specific meanwhile. The functions are moved to block/raw-{posix,win32}.c and qemu-img.c calls bdrv_get_allocated_file_size to count the bs. And also added VMDK code to count his own extents. Signed-off-by: Fam Zheng <famcool@gmail.com> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
ae261c86aa
commit
4a1d5e1fde
19
block.c
19
block.c
@ -1146,6 +1146,25 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of a allocated file in bytes. Sparse files are counted by actual
|
||||
* allocated space. Return < 0 if error or unknown.
|
||||
*/
|
||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
if (drv->bdrv_get_allocated_file_size) {
|
||||
return drv->bdrv_get_allocated_file_size(bs);
|
||||
}
|
||||
if (bs->file) {
|
||||
return bdrv_get_allocated_file_size(bs->file);
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of a file in bytes. Return < 0 if error or unknown.
|
||||
*/
|
||||
|
1
block.h
1
block.h
@ -89,6 +89,7 @@ int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
int bdrv_truncate(BlockDriverState *bs, int64_t offset);
|
||||
int64_t bdrv_getlength(BlockDriverState *bs);
|
||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
|
||||
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
|
||||
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
|
||||
int bdrv_commit(BlockDriverState *bs);
|
||||
|
@ -793,6 +793,17 @@ static int64_t raw_getlength(BlockDriverState *bs)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
struct stat st;
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (fstat(s->fd, &st) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
int fd;
|
||||
@ -888,6 +899,8 @@ static BlockDriver bdrv_file = {
|
||||
|
||||
.bdrv_truncate = raw_truncate,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
};
|
||||
@ -1156,6 +1169,8 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* generic scsi device */
|
||||
#ifdef __linux__
|
||||
@ -1277,6 +1292,8 @@ static BlockDriver bdrv_host_floppy = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = floppy_is_inserted,
|
||||
@ -1380,6 +1397,8 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
@ -1503,6 +1522,8 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
|
@ -213,6 +213,31 @@ static int64_t raw_getlength(BlockDriverState *bs)
|
||||
return l.QuadPart;
|
||||
}
|
||||
|
||||
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
|
||||
DWORD * high);
|
||||
get_compressed_t get_compressed;
|
||||
struct _stati64 st;
|
||||
const char *filename = bs->filename;
|
||||
/* WinNT support GetCompressedFileSize to determine allocate size */
|
||||
get_compressed =
|
||||
(get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
|
||||
"GetCompressedFileSizeA");
|
||||
if (get_compressed) {
|
||||
DWORD high, low;
|
||||
low = get_compressed(filename, &high);
|
||||
if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
|
||||
return (((int64_t) high) << 32) + low;
|
||||
}
|
||||
}
|
||||
|
||||
if (_stati64(filename, &st) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
int fd;
|
||||
@ -257,6 +282,8 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_truncate = raw_truncate,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
};
|
||||
@ -419,6 +446,8 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
};
|
||||
|
||||
static void bdrv_file_init(void)
|
||||
|
24
block/vmdk.c
24
block/vmdk.c
@ -1289,6 +1289,29 @@ static int vmdk_flush(BlockDriverState *bs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
int i;
|
||||
int64_t ret = 0;
|
||||
int64_t r;
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
|
||||
ret = bdrv_get_allocated_file_size(bs->file);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < s->num_extents; i++) {
|
||||
if (s->extents[i].file == bs->file) {
|
||||
continue;
|
||||
}
|
||||
r = bdrv_get_allocated_file_size(s->extents[i].file);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
ret += r;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vmdk_create_options[] = {
|
||||
{
|
||||
@ -1327,6 +1350,7 @@ static BlockDriver bdrv_vmdk = {
|
||||
.bdrv_create = vmdk_create,
|
||||
.bdrv_flush = vmdk_flush,
|
||||
.bdrv_is_allocated = vmdk_is_allocated,
|
||||
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
|
||||
|
||||
.create_options = vmdk_create_options,
|
||||
};
|
||||
|
@ -86,6 +86,7 @@ struct BlockDriver {
|
||||
const char *protocol_name;
|
||||
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
|
||||
int64_t (*bdrv_getlength)(BlockDriverState *bs);
|
||||
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
|
||||
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
|
||||
|
31
qemu-img.c
31
qemu-img.c
@ -1024,35 +1024,6 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static int64_t get_allocated_file_size(const char *filename)
|
||||
{
|
||||
typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
|
||||
get_compressed_t get_compressed;
|
||||
struct _stati64 st;
|
||||
|
||||
/* WinNT support GetCompressedFileSize to determine allocate size */
|
||||
get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
|
||||
if (get_compressed) {
|
||||
DWORD high, low;
|
||||
low = get_compressed(filename, &high);
|
||||
if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
|
||||
return (((int64_t) high) << 32) + low;
|
||||
}
|
||||
|
||||
if (_stati64(filename, &st) < 0)
|
||||
return -1;
|
||||
return st.st_size;
|
||||
}
|
||||
#else
|
||||
static int64_t get_allocated_file_size(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(filename, &st) < 0)
|
||||
return -1;
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dump_snapshots(BlockDriverState *bs)
|
||||
{
|
||||
@ -1112,7 +1083,7 @@ static int img_info(int argc, char **argv)
|
||||
bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
|
||||
bdrv_get_geometry(bs, &total_sectors);
|
||||
get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
|
||||
allocated_size = get_allocated_file_size(filename);
|
||||
allocated_size = bdrv_get_allocated_file_size(bs);
|
||||
if (allocated_size < 0) {
|
||||
snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user