From patchwork Wed Mar 11 10:28:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Denis V. Lunev" X-Patchwork-Id: 448913 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6E8DF14016B for ; Wed, 11 Mar 2015 21:34:36 +1100 (AEDT) Received: from localhost ([::1]:53627 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVdyE-0003SP-8M for incoming@patchwork.ozlabs.org; Wed, 11 Mar 2015 06:34:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34494) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVdrk-0008PZ-8s for qemu-devel@nongnu.org; Wed, 11 Mar 2015 06:27:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YVdrf-0003xY-7h for qemu-devel@nongnu.org; Wed, 11 Mar 2015 06:27:52 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:32617 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVdre-0003uG-K3 for qemu-devel@nongnu.org; Wed, 11 Mar 2015 06:27:46 -0400 Received: from hades.sw.ru ([10.30.8.132]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id t2BARgbk017637; Wed, 11 Mar 2015 13:27:43 +0300 (MSK) From: "Denis V. Lunev" To: Date: Wed, 11 Mar 2015 13:28:18 +0300 Message-Id: <1426069701-1405-25-git-send-email-den@openvz.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1426069701-1405-1-git-send-email-den@openvz.org> References: <1426069701-1405-1-git-send-email-den@openvz.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.0 [fuzzy] X-Received-From: 195.214.232.25 Cc: Kevin Wolf , "Denis V. Lunev" , qemu-devel@nongnu.org, Stefan Hajnoczi Subject: [Qemu-devel] [PATCH 24/27] block/parallels: delay writing to BAT till bdrv_co_flush_to_os X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Reviewed-by: Roman Kagan CC: Kevin Wolf CC: Stefan Hajnoczi Reviewed-by: Stefan Hajnoczi --- block/parallels.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/block/parallels.c b/block/parallels.c index f0518be..6e7f000 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" /**************************************************************/ @@ -62,6 +63,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; @@ -136,7 +140,6 @@ static int64_t allocate_cluster(BlockDriverState *bs, int64_t sector_num) BDRVParallelsState *s = bs->opaque; uint32_t idx, offset; int64_t pos; - int ret; idx = sector_num / s->tracks; offset = sector_num % s->tracks; @@ -152,14 +155,43 @@ static int64_t allocate_cluster(BlockDriverState *bs, int64_t sector_num) bdrv_truncate(bs->file, (pos + s->tracks) << BDRV_SECTOR_BITS); 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) { - 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) { @@ -542,6 +574,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; @@ -563,6 +599,7 @@ static void parallels_close(BlockDriverState *bs) parallels_update_header(bs); } + g_free(s->bat_dirty_bmap); qemu_vfree(s->header); } @@ -592,6 +629,7 @@ static BlockDriver bdrv_parallels = { .bdrv_open = parallels_open, .bdrv_close = parallels_close, .bdrv_co_get_block_status = parallels_co_get_block_status, + .bdrv_co_flush_to_os = parallels_co_flush_to_os, .bdrv_co_readv = parallels_co_readv, .bdrv_co_writev = parallels_co_writev,