From patchwork Tue Jul 24 11:04:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 172882 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B67F62C008A for ; Tue, 24 Jul 2012 22:47:53 +1000 (EST) Received: from localhost ([::1]:51212 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SteWl-0005oc-To for incoming@patchwork.ozlabs.org; Tue, 24 Jul 2012 08:47:51 -0400 Received: from eggs.gnu.org ([208.118.235.92]:57040) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Stcwr-0008SU-4x for qemu-devel@nongnu.org; Tue, 24 Jul 2012 07:06:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Stcwi-0005tV-3o for qemu-devel@nongnu.org; Tue, 24 Jul 2012 07:06:40 -0400 Received: from mail-yw0-f45.google.com ([209.85.213.45]:36778) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Stcwh-00058R-Vk for qemu-devel@nongnu.org; Tue, 24 Jul 2012 07:06:32 -0400 Received: by mail-yw0-f45.google.com with SMTP id p34so6575216yhp.4 for ; Tue, 24 Jul 2012 04:06:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=unmivp0ZybpLODcDUfP3bGyabxkqo3v697PZYFnorN4=; b=U37Uw6h8ikRF0rTIBdX5vHNxXrEu5byw7kZrAwyXzpk922VLn4Ai+CdJzaaNSHISEG EI+tDUjSuWp1aUjDeNLA39MCZo6+FxaPikpvX+dGgxFArB928/5zjclS81NP2Gxce+iT 8HHHCymW8m6lhEyXmshSWX3Ak7zZofBPZ5xa0stPeb5WsPxz6zyOlzSsSIoToP9myzBL r5E4xSnGZW3G5UJUqOtXiUhK+cG1p+yM4nZRWU3m8iMUOKtvzdnDX4TaHQsaPL0Qxqbo O4K2eygNqXuNX+qwWWDRf9DB/7HCZUEqRnSQWegJw3OlED9tpsEEwtHoe0w0XPBliucr to6A== Received: by 10.42.10.73 with SMTP id p9mr14394414icp.43.1343127991627; Tue, 24 Jul 2012 04:06:31 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-189-113.ip51.fastwebnet.it. [93.34.189.113]) by mx.google.com with ESMTPS id if4sm1752561igc.10.2012.07.24.04.06.28 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 24 Jul 2012 04:06:30 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 24 Jul 2012 13:04:16 +0200 Message-Id: <1343127865-16608-39-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1343127865-16608-1-git-send-email-pbonzini@redhat.com> References: <1343127865-16608-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.213.45 Cc: kwolf@redhat.com, jcody@redhat.com, eblake@redhat.com, stefanha@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 38/47] block: implement dirty bitmap using HBitmap 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 This starts using HBitmap for the dirty bitmap in the block layer, and converts mirroring to use an HBitmapIter. Signed-off-by: Paolo Bonzini --- Makefile.objs | 2 +- block.c | 94 +++++++++----------------------------------------------- block.h | 6 ++-- block/mirror.c | 12 ++++++-- block_int.h | 4 +-- trace-events | 1 + 6 files changed, 33 insertions(+), 86 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 67e9d8d..fa7f6d5 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -43,7 +43,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o -block-obj-y += qemu-progress.o qemu-sockets.o +block-obj-y += qemu-progress.o qemu-sockets.o hbitmap.o block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/block.c b/block.c index 65d9bed..54d0cec 100644 --- a/block.c +++ b/block.c @@ -1026,7 +1026,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, bs_dest->iostatus = bs_src->iostatus; /* dirty bitmap */ - bs_dest->dirty_count = bs_src->dirty_count; bs_dest->dirty_bitmap = bs_src->dirty_bitmap; /* job */ @@ -1669,36 +1668,6 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, return ret; } -#define BITS_PER_LONG (sizeof(unsigned long) * 8) - -static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int dirty) -{ - int64_t start, end; - unsigned long val, idx, bit; - - start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK; - end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK; - - for (; start <= end; start++) { - idx = start / BITS_PER_LONG; - bit = start % BITS_PER_LONG; - val = bs->dirty_bitmap[idx]; - if (dirty) { - if (!(val & (1UL << bit))) { - bs->dirty_count++; - val |= 1UL << bit; - } - } else { - if (val & (1UL << bit)) { - bs->dirty_count--; - val &= ~(1UL << bit); - } - } - bs->dirty_bitmap[idx] = val; - } -} - /* Return < 0 if error. Important errors are: -EIO generic I/O error (may happen for all errors) -ENOMEDIUM No media inserted. @@ -3813,18 +3782,15 @@ void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable) { int64_t bitmap_size; - bs->dirty_count = 0; if (enable) { if (!bs->dirty_bitmap) { - bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) + - BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG - 1; - bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG; - - bs->dirty_bitmap = g_new0(unsigned long, bitmap_size); + bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS); + bs->dirty_bitmap = hbitmap_alloc(bitmap_size, + BDRV_LOG_SECTORS_PER_DIRTY_CHUNK); } } else { if (bs->dirty_bitmap) { - g_free(bs->dirty_bitmap); + hbitmap_free(bs->dirty_bitmap); bs->dirty_bitmap = NULL; } } @@ -3832,67 +3798,37 @@ void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable) int bdrv_get_dirty(BlockDriverState *bs, int64_t sector) { - int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK; - - if (bs->dirty_bitmap && - (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) { - return !!(bs->dirty_bitmap[chunk / BITS_PER_LONG] & - (1UL << (chunk % BITS_PER_LONG))); + if (bs->dirty_bitmap) { + return hbitmap_get(bs->dirty_bitmap, sector); } else { return 0; } } -int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector) +void bdrv_dirty_iter_init(BlockDriverState *bs, HBitmapIter *hbi) { - int64_t chunk; - int bit, elem; - - /* Avoid an infinite loop. */ - assert(bs->dirty_count > 0); - - sector = (sector | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1; - chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK; - - QEMU_BUILD_BUG_ON(sizeof(bs->dirty_bitmap[0]) * 8 != BITS_PER_LONG); - elem = chunk / BITS_PER_LONG; - bit = chunk % BITS_PER_LONG; - for (;;) { - if (sector >= bs->total_sectors) { - sector = 0; - bit = elem = 0; - } - if (bit == 0 && bs->dirty_bitmap[elem] == 0) { - sector += BDRV_SECTORS_PER_DIRTY_CHUNK * BITS_PER_LONG; - elem++; - } else { - if (bs->dirty_bitmap[elem] & (1UL << bit)) { - return sector; - } - sector += BDRV_SECTORS_PER_DIRTY_CHUNK; - if (++bit == BITS_PER_LONG) { - bit = 0; - elem++; - } - } - } + hbitmap_iter_init(hbi, bs->dirty_bitmap, 0); } void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors) { - set_dirty_bitmap(bs, cur_sector, nr_sectors, 1); + hbitmap_set(bs->dirty_bitmap, cur_sector, nr_sectors); } void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors) { - set_dirty_bitmap(bs, cur_sector, nr_sectors, 0); + hbitmap_reset(bs->dirty_bitmap, cur_sector, nr_sectors); } int64_t bdrv_get_dirty_count(BlockDriverState *bs) { - return bs->dirty_count; + if (bs->dirty_bitmap) { + return hbitmap_count(bs->dirty_bitmap) >> BDRV_LOG_SECTORS_PER_DIRTY_CHUNK; + } else { + return 0; + } } void bdrv_set_in_use(BlockDriverState *bs, int in_use) diff --git a/block.h b/block.h index e7440f6..8212a0f 100644 --- a/block.h +++ b/block.h @@ -324,13 +324,15 @@ int bdrv_img_create(const char *filename, const char *fmt, void bdrv_set_buffer_alignment(BlockDriverState *bs, int align); void *qemu_blockalign(BlockDriverState *bs, size_t size); -#define BDRV_SECTORS_PER_DIRTY_CHUNK 2048 +#define BDRV_SECTORS_PER_DIRTY_CHUNK (1 << BDRV_LOG_SECTORS_PER_DIRTY_CHUNK) +#define BDRV_LOG_SECTORS_PER_DIRTY_CHUNK 11 +struct HBitmapIter; void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable); int bdrv_get_dirty(BlockDriverState *bs, int64_t sector); void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); -int64_t bdrv_get_next_dirty(BlockDriverState *bs, int64_t sector); +void bdrv_dirty_iter_init(BlockDriverState *bs, struct HBitmapIter *hbi); int64_t bdrv_get_dirty_count(BlockDriverState *bs); void bdrv_enable_copy_on_read(BlockDriverState *bs); diff --git a/block/mirror.c b/block/mirror.c index fb54d27..c3340d1 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -36,6 +36,7 @@ typedef struct MirrorBlockJob { bool synced; bool complete; int64_t sector_num; + HBitmapIter hbi; uint8_t *buf; } MirrorBlockJob; @@ -49,8 +50,15 @@ static int coroutine_fn mirror_iteration(MirrorBlockJob *s, int64_t end; struct iovec iov; + s->sector_num = hbitmap_iter_next(&s->hbi); + if (s->sector_num < 0) { + bdrv_dirty_iter_init(source, &s->hbi); + s->sector_num = hbitmap_iter_next(&s->hbi); + trace_mirror_restart_iter(s, bdrv_get_dirty_count(source)); + assert(s->sector_num >= 0); + } + end = s->common.len >> BDRV_SECTOR_BITS; - s->sector_num = bdrv_get_next_dirty(source, s->sector_num); nb_sectors = MIN(BDRV_SECTORS_PER_DIRTY_CHUNK, end - s->sector_num); bdrv_reset_dirty(source, s->sector_num, nb_sectors); @@ -127,7 +135,7 @@ static void coroutine_fn mirror_run(void *opaque) goto immediate_exit; } - s->sector_num = -1; + bdrv_dirty_iter_init(bs, &s->hbi); for (;;) { uint64_t delay_ns; int64_t cnt; diff --git a/block_int.h b/block_int.h index 0de2fdc..4cb3c5b 100644 --- a/block_int.h +++ b/block_int.h @@ -30,6 +30,7 @@ #include "qemu-coroutine.h" #include "qemu-timer.h" #include "qapi-types.h" +#include "hbitmap.h" #include "monitor.h" #define BLOCK_FLAG_ENCRYPT 1 @@ -258,8 +259,7 @@ struct BlockDriverState { bool iostatus_enabled; BlockDeviceIoStatus iostatus; char device_name[32]; - unsigned long *dirty_bitmap; - int64_t dirty_count; + HBitmap *dirty_bitmap; int in_use; /* users other than guest access, eg. block migration */ QTAILQ_ENTRY(BlockDriverState) list; diff --git a/trace-events b/trace-events index 9313ae7..496824c 100644 --- a/trace-events +++ b/trace-events @@ -77,6 +77,7 @@ stream_start(void *bs, void *base, void *s, void *co, void *opaque) "bs %p base # block/mirror.c mirror_start(void *bs, void *s, void *co, void *opaque) "bs %p s %p co %p opaque %p" +mirror_restart_iter(void *s, int64_t cnt) "s %p dirty count %"PRId64 mirror_before_flush(void *s) "s %p" mirror_before_drain(void *s, int64_t cnt) "s %p dirty count %"PRId64 mirror_before_sleep(void *s, int64_t cnt, int synced) "s %p dirty count %"PRId64" synced %d"