diff options
author | Denis V. Lunev <den@openvz.org> | 2015-04-28 10:46:57 +0300 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2015-05-22 09:37:32 +0100 |
commit | 0d31c7c200b3dca2aeeaa6f74ff3fd539aad803a (patch) | |
tree | e8b2a49fe7133c5c81387cbcc1406518789e6b2a /block/parallels.c | |
parent | 2d68e22e94e8bc5a0d32a38b53c592c320db8261 (diff) |
block/parallels: delay writing to BAT till bdrv_co_flush_to_os
The idea is that we do not need to immediately sync BAT to the image as
from the guest point of view there is a possibility that IO is lost
even in the physical controller until flush command was finished.
bdrv_co_flush_to_os is exactly the right place for this purpose.
Technically the patch uses loaded BAT data as a cache and performs
actual on-disk metadata updates in parallels_co_flush_to_os callback.
This patch speed ups
qemu-img create -f parallels -o cluster_size=64k ./1.hds 64G
qemu-io -f parallels -c "write -P 0x11 0 1024k" 1.hds
writing from 50-60 Mb/sec to 80-90 Mb/sec on rotational media and
from 160 Mb/sec to 190 Mb/sec on SSD disk.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Roman Kagan <rkagan@parallels.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Roman Kagan <rkagan@parallels.com>
Message-id: 1430207220-24458-25-git-send-email-den@openvz.org
CC: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/parallels.c')
-rw-r--r-- | block/parallels.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/block/parallels.c b/block/parallels.c index 4d8a0d48aa..05fe030f05 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -30,6 +30,7 @@ #include "qemu-common.h" #include "block/block_int.h" #include "qemu/module.h" +#include "qemu/bitmap.h" /**************************************************************/ @@ -66,6 +67,9 @@ typedef struct BDRVParallelsState { uint32_t header_size; bool header_unclean; + unsigned long *bat_dirty_bmap; + unsigned int bat_dirty_block; + uint32_t *bat_bitmap; unsigned int bat_size; @@ -165,15 +169,43 @@ static int64_t allocate_cluster(BlockDriverState *bs, int64_t sector_num) } s->bat_bitmap[idx] = cpu_to_le32(pos / s->off_multiplier); - ret = bdrv_pwrite(bs->file, bat_entry_off(idx), s->bat_bitmap + idx, - sizeof(s->bat_bitmap[idx])); - if (ret < 0) { - s->bat_bitmap[idx] = 0; - return ret; - } + + bitmap_set(s->bat_dirty_bmap, bat_entry_off(idx) / s->bat_dirty_block, 1); return bat2sect(s, idx) + offset; } + +static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs) +{ + BDRVParallelsState *s = bs->opaque; + unsigned long size = DIV_ROUND_UP(s->header_size, s->bat_dirty_block); + unsigned long bit; + + qemu_co_mutex_lock(&s->lock); + + bit = find_first_bit(s->bat_dirty_bmap, size); + while (bit < size) { + uint32_t off = bit * s->bat_dirty_block; + uint32_t to_write = s->bat_dirty_block; + int ret; + + if (off + to_write > s->header_size) { + to_write = s->header_size - off; + } + ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off, to_write); + if (ret < 0) { + qemu_co_mutex_unlock(&s->lock); + return ret; + } + bit = find_next_bit(s->bat_dirty_bmap, size, bit + 1); + } + bitmap_zero(s->bat_dirty_bmap, size); + + qemu_co_mutex_unlock(&s->lock); + return 0; +} + + static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { @@ -557,6 +589,10 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, } } + s->bat_dirty_block = 4 * getpagesize(); + s->bat_dirty_bmap = + bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block)); + qemu_co_mutex_init(&s->lock); return 0; @@ -578,6 +614,7 @@ static void parallels_close(BlockDriverState *bs) parallels_update_header(bs); } + g_free(s->bat_dirty_bmap); qemu_vfree(s->header); } @@ -608,6 +645,7 @@ static BlockDriver bdrv_parallels = { .bdrv_close = parallels_close, .bdrv_co_get_block_status = parallels_co_get_block_status, .bdrv_has_zero_init = bdrv_has_zero_init_1, + .bdrv_co_flush_to_os = parallels_co_flush_to_os, .bdrv_co_readv = parallels_co_readv, .bdrv_co_writev = parallels_co_writev, |