[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 11/15] vmdk: add bdrv_co_write_zeroes
From: |
Stefan Hajnoczi |
Subject: |
[Qemu-devel] [PATCH 11/15] vmdk: add bdrv_co_write_zeroes |
Date: |
Fri, 3 May 2013 13:52:48 +0200 |
From: Fam Zheng <address@hidden>
Use special offset to write zeroes efficiently, when zeroed-grain GTE is
available. If zero-write an allocated cluster, cluster is leaked because
its offset pointer is overwritten by "0x1".
Signed-off-by: Fam Zheng <address@hidden>
Signed-off-by: Stefan Hajnoczi <address@hidden>
---
block/vmdk.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 68 insertions(+), 18 deletions(-)
diff --git a/block/vmdk.c b/block/vmdk.c
index d98f304..608daaf 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -124,6 +124,7 @@ typedef struct VmdkMetaData {
unsigned int l2_index;
unsigned int l2_offset;
int valid;
+ uint32_t *l2_cache_entry;
} VmdkMetaData;
typedef struct VmdkGrainMarker {
@@ -835,6 +836,9 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData
*m_data)
return VMDK_ERROR;
}
}
+ if (m_data->l2_cache_entry) {
+ *m_data->l2_cache_entry = offset;
+ }
return VMDK_OK;
}
@@ -905,6 +909,14 @@ static int get_cluster_offset(BlockDriverState *bs,
l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
*cluster_offset = le32_to_cpu(l2_table[l2_index]);
+ if (m_data) {
+ m_data->valid = 1;
+ m_data->l1_index = l1_index;
+ m_data->l2_index = l2_index;
+ m_data->offset = *cluster_offset;
+ m_data->l2_offset = l2_offset;
+ m_data->l2_cache_entry = &l2_table[l2_index];
+ }
if (extent->has_zero_grain && *cluster_offset == VMDK_GTE_ZEROED) {
zeroed = true;
}
@@ -938,10 +950,6 @@ static int get_cluster_offset(BlockDriverState *bs,
if (m_data) {
m_data->offset = *cluster_offset;
- m_data->l1_index = l1_index;
- m_data->l2_index = l2_index;
- m_data->l2_offset = l2_offset;
- m_data->valid = 1;
}
}
*cluster_offset <<= 9;
@@ -1164,8 +1172,17 @@ static coroutine_fn int vmdk_co_read(BlockDriverState
*bs, int64_t sector_num,
return ret;
}
+/**
+ * vmdk_write:
+ * @zeroed: buf is ignored (data is zero), use zeroed_grain GTE feature
+ * if possible, otherwise return -ENOTSUP.
+ * @zero_dry_run: used for zeroed == true only, don't update L2 table, just
+ *
+ * Returns: error code with 0 for success.
+ */
static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
- const uint8_t *buf, int nb_sectors)
+ const uint8_t *buf, int nb_sectors,
+ bool zeroed, bool zero_dry_run)
{
BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent = NULL;
@@ -1211,7 +1228,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t
sector_num,
&cluster_offset);
}
}
- if (ret) {
+ if (ret == VMDK_ERROR) {
return -EINVAL;
}
extent_begin_sector = extent->end_sector - extent->sectors;
@@ -1221,17 +1238,34 @@ static int vmdk_write(BlockDriverState *bs, int64_t
sector_num,
if (n > nb_sectors) {
n = nb_sectors;
}
-
- ret = vmdk_write_extent(extent,
- cluster_offset, index_in_cluster * 512,
- buf, n, sector_num);
- if (ret) {
- return ret;
- }
- if (m_data.valid) {
- /* update L2 tables */
- if (vmdk_L2update(extent, &m_data) == -1) {
- return -EIO;
+ if (zeroed) {
+ /* Do zeroed write, buf is ignored */
+ if (extent->has_zero_grain &&
+ index_in_cluster == 0 &&
+ n >= extent->cluster_sectors) {
+ n = extent->cluster_sectors;
+ if (!zero_dry_run) {
+ m_data.offset = VMDK_GTE_ZEROED;
+ /* update L2 tables */
+ if (vmdk_L2update(extent, &m_data) != VMDK_OK) {
+ return -EIO;
+ }
+ }
+ } else {
+ return -ENOTSUP;
+ }
+ } else {
+ ret = vmdk_write_extent(extent,
+ cluster_offset, index_in_cluster * 512,
+ buf, n, sector_num);
+ if (ret) {
+ return ret;
+ }
+ if (m_data.valid) {
+ /* update L2 tables */
+ if (vmdk_L2update(extent, &m_data) != VMDK_OK) {
+ return -EIO;
+ }
}
}
nb_sectors -= n;
@@ -1257,7 +1291,22 @@ static coroutine_fn int vmdk_co_write(BlockDriverState
*bs, int64_t sector_num,
int ret;
BDRVVmdkState *s = bs->opaque;
qemu_co_mutex_lock(&s->lock);
- ret = vmdk_write(bs, sector_num, buf, nb_sectors);
+ ret = vmdk_write(bs, sector_num, buf, nb_sectors, false, false);
+ qemu_co_mutex_unlock(&s->lock);
+ return ret;
+}
+
+static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
+ int64_t sector_num,
+ int nb_sectors)
+{
+ int ret;
+ BDRVVmdkState *s = bs->opaque;
+ qemu_co_mutex_lock(&s->lock);
+ ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, true);
+ if (!ret) {
+ ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, false);
+ }
qemu_co_mutex_unlock(&s->lock);
return ret;
}
@@ -1737,6 +1786,7 @@ static BlockDriver bdrv_vmdk = {
.bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_read = vmdk_co_read,
.bdrv_write = vmdk_co_write,
+ .bdrv_co_write_zeroes = vmdk_co_write_zeroes,
.bdrv_close = vmdk_close,
.bdrv_create = vmdk_create,
.bdrv_co_flush_to_disk = vmdk_co_flush,
--
1.8.1.4
- [Qemu-devel] [PATCH 01/15] qemu: add castagnoli crc32c checksum algorithm, (continued)
- [Qemu-devel] [PATCH 01/15] qemu: add castagnoli crc32c checksum algorithm, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 02/15] block: vhdx header for the QEMU support of VHDX images, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 04/15] block: add read-only support to VHDX image format., Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 03/15] block: initial VHDX driver support framework - supports open and probe, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 05/15] blockdev: Replace "undefined error" in qmp_block_resize, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 06/15] vmdk: named return code., Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 07/15] vmdk: add support for “zeroed‐grain” GTE, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 08/15] vmdk: Add option to create zeroed-grain image, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 09/15] vmdk: change magic number to macro, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 10/15] vmdk: store fields of VmdkMetaData in cpu endian, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 11/15] vmdk: add bdrv_co_write_zeroes,
Stefan Hajnoczi <=
- [Qemu-devel] [PATCH 12/15] qemu-iotests: Filter out vmdk creation options, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 13/15] nbd: use g_slice_new() instead of a freelist, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 14/15] nbd: support large NBD requests, Stefan Hajnoczi, 2013/05/03
- [Qemu-devel] [PATCH 15/15] qemu-iotests: Filter out 'adapter_type', Stefan Hajnoczi, 2013/05/03