summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFam Zheng <famcool@gmail.com>2011-07-12 19:56:39 +0800
committerKevin Wolf <kwolf@redhat.com>2011-07-19 15:39:08 +0200
commit4a1d5e1fded54358ddc4d8cbd53388ca7c93499b (patch)
treee317502ecc47e7cf31ab53bbc3f4dd2c9b92c7f0
parentae261c86aaed62e7acddafab8262a2bf286d40b7 (diff)
downloadqemu-4a1d5e1fded54358ddc4d8cbd53388ca7c93499b.tar.gz
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>
-rw-r--r--block.c19
-rw-r--r--block.h1
-rw-r--r--block/raw-posix.c21
-rw-r--r--block/raw-win32.c29
-rw-r--r--block/vmdk.c24
-rw-r--r--block_int.h1
-rw-r--r--qemu-img.c31
7 files changed, 96 insertions, 30 deletions
diff --git a/block.c b/block.c
index 24a25d569b..9549b9eff9 100644
--- a/block.c
+++ b/block.c
@@ -1147,6 +1147,25 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
}
/**
+ * 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.
*/
int64_t bdrv_getlength(BlockDriverState *bs)
diff --git a/block.h b/block.h
index 859d1d9835..59cc410e3b 100644
--- a/block.h
+++ b/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);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 34b64aa205..cd89c8312a 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -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,
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 56bd7195a1..91067e7595 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -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)
diff --git a/block/vmdk.c b/block/vmdk.c
index de08d0ce2d..37478d2553 100644
--- a/block/vmdk.c
+++ b/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,
};
diff --git a/block_int.h b/block_int.h
index 8a7b6cbb42..efb68038c4 100644
--- a/block_int.h
+++ b/block_int.h
@@ -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);
diff --git a/qemu-img.c b/qemu-img.c
index 54137a4e92..b205e98dd2 100644
--- a/qemu-img.c
+++ b/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 {