From patchwork Mon Nov 2 13:40:41 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liran Schour X-Patchwork-Id: 37414 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D6393B7BB0 for ; Tue, 3 Nov 2009 00:06:54 +1100 (EST) Received: from localhost ([127.0.0.1]:58009 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N4wcU-0005oP-UU for incoming@patchwork.ozlabs.org; Mon, 02 Nov 2009 08:06:51 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1N4wb9-0005Ap-RC for qemu-devel@nongnu.org; Mon, 02 Nov 2009 08:05:27 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1N4wb4-00054W-Rv for qemu-devel@nongnu.org; Mon, 02 Nov 2009 08:05:26 -0500 Received: from [199.232.76.173] (port=54130 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N4wb4-00054D-IG for qemu-devel@nongnu.org; Mon, 02 Nov 2009 08:05:22 -0500 Received: from mtagate2.de.ibm.com ([195.212.17.162]:40127) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1N4wb3-0003iW-KZ for qemu-devel@nongnu.org; Mon, 02 Nov 2009 08:05:22 -0500 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate2.de.ibm.com (8.13.1/8.13.1) with ESMTP id nA2D5IKB021362 for ; Mon, 2 Nov 2009 13:05:18 GMT Received: from d12av04.megacenter.de.ibm.com (d12av04.megacenter.de.ibm.com [9.149.165.229]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id nA2D5Ir51151122 for ; Mon, 2 Nov 2009 14:05:18 +0100 Received: from d12av04.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av04.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id nA2D5HGh005145 for ; Mon, 2 Nov 2009 14:05:17 +0100 Received: from localhost.localdomain (im4-64s.haifa.ibm.com [9.148.27.41]) by d12av04.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id nA2D5HTV005142; Mon, 2 Nov 2009 14:05:17 +0100 From: lirans@il.ibm.com To: qemu-devel@nongnu.org Date: Mon, 2 Nov 2009 15:40:41 +0200 Message-Id: <12571692413903-git-send-email-lirans@il.ibm.com> X-Mailer: git-send-email 1.5.2.4 X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: Liran Schour Subject: [Qemu-devel] [PATCH 1/3 v5] Expose a mechanism to trace block writes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org To support live migration without shared storage we need to be able to trace writes to disk while migrating. This Patch expose dirty block tracking per device to be polled from upper layer. Changes from v4: - Register dirty tracking for each block device. - Minor coding style issues. - Block.c will now manage a dirty bitmap per device once bdrv_set_dirty_tracking() is called. Bitmap is polled by the upper layer (block-migration.c). Signed-off-by: Liran Schour diff --git a/block.c b/block.c index fa0de25..d316eeb 100644 --- a/block.c +++ b/block.c @@ -43,6 +43,7 @@ #define SECTOR_BITS 9 #define SECTOR_SIZE (1 << SECTOR_BITS) +#define SECTORS_PER_DIRTY_CHUNK 8 static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, @@ -609,6 +610,18 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num, return drv->bdrv_read(bs, sector_num, buf, nb_sectors); } +static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int dirty) +{ + int64_t start, end; + start = sector_num / SECTORS_PER_DIRTY_CHUNK; + end = (sector_num + nb_sectors) / SECTORS_PER_DIRTY_CHUNK; + + for(; start <= end; start++) { + bs->dirty_bitmap[start] = dirty; + } +} + /* Return < 0 if error. Important errors are: -EIO generic I/O error (may happen for all errors) -ENOMEDIUM No media inserted. @@ -625,7 +638,11 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, return -EACCES; if (bdrv_check_request(bs, sector_num, nb_sectors)) return -EIO; - + + if(bs->dirty_tracking) { + set_dirty_bitmap(bs, sector_num, nb_sectors, 1); + } + return drv->bdrv_write(bs, sector_num, buf, nb_sectors); } @@ -1162,6 +1179,11 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, return -ENOTSUP; if (bdrv_check_request(bs, sector_num, nb_sectors)) return -EIO; + + if(bs->dirty_tracking) { + set_dirty_bitmap(bs, sector_num, nb_sectors, 1); + } + return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors); } @@ -1359,6 +1381,10 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, if (bdrv_check_request(bs, sector_num, nb_sectors)) return NULL; + if(bs->dirty_tracking) { + set_dirty_bitmap(bs, sector_num, nb_sectors, 1); + } + ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors, cb, opaque); @@ -1883,7 +1909,57 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, return NULL; } + + void *qemu_blockalign(BlockDriverState *bs, size_t size) { return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size); } + +void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable) +{ + int64_t bitmap_size; + if(enable) { + if(bs->dirty_tracking == 0) { + int64_t i; + uint8_t test; + bitmap_size = (bdrv_getlength(bs) >> SECTOR_BITS); + bitmap_size /= SECTORS_PER_DIRTY_CHUNK; + bitmap_size++; + + bs->dirty_bitmap = qemu_mallocz(bitmap_size); + + bs->dirty_tracking = enable; + for(i = 0; i < bitmap_size; i++) test = bs->dirty_bitmap[i]; + } + } else { + if(bs->dirty_tracking != 0) { + qemu_free(bs->dirty_bitmap); + bs->dirty_tracking = enable; + } + } +} + +int bdrv_get_dirty(BlockDriverState *bs, int64_t sector) +{ + int64_t chunk = sector / (int64_t)SECTORS_PER_DIRTY_CHUNK; + + if(bs->dirty_bitmap != NULL && + (sector << SECTOR_BITS) <= bdrv_getlength(bs)) { + return bs->dirty_bitmap[chunk]; + } else { + return 0; + } +} + +void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, + int nr_sectors) +{ + set_dirty_bitmap(bs, cur_sector, nr_sectors, 0); +} + +int bdrv_get_sectors_per_chunk(void) +{ + /* size must be 2^x */ + return SECTORS_PER_DIRTY_CHUNK; +} diff --git a/block.h b/block.h index a966afb..8a5e7ce 100644 --- a/block.h +++ b/block.h @@ -78,7 +78,8 @@ void bdrv_register(BlockDriver *bdrv); /* async block I/O */ typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); - +typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector, + int sector_num); BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); @@ -184,4 +185,9 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size); +void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable); +int bdrv_get_dirty(BlockDriverState *bs, int64_t sector); +void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, + int nr_sectors); +int bdrv_get_sectors_per_chunk(void); #endif diff --git a/block_int.h b/block_int.h index 8e72abe..7ebe926 100644 --- a/block_int.h +++ b/block_int.h @@ -168,6 +168,8 @@ struct BlockDriverState { int cyls, heads, secs, translation; int type; char device_name[32]; + int dirty_tracking; + uint8_t *dirty_bitmap; BlockDriverState *next; void *private; };