block: allow customizing the granularity of the dirty bitmap

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Paolo Bonzini 2013-01-21 17:09:45 +01:00 committed by Kevin Wolf
parent acc906c6c5
commit 50717e941b
5 changed files with 21 additions and 24 deletions

View File

@ -23,7 +23,8 @@
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include <assert.h> #include <assert.h>
#define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS) #define BLOCK_SIZE (1 << 20)
#define BDRV_SECTORS_PER_DIRTY_CHUNK (BLOCK_SIZE >> BDRV_SECTOR_BITS)
#define BLK_MIG_FLAG_DEVICE_BLOCK 0x01 #define BLK_MIG_FLAG_DEVICE_BLOCK 0x01
#define BLK_MIG_FLAG_EOS 0x02 #define BLK_MIG_FLAG_EOS 0x02
@ -254,7 +255,7 @@ static void set_dirty_tracking(int enable)
BlkMigDevState *bmds; BlkMigDevState *bmds;
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
bdrv_set_dirty_tracking(bmds->bs, enable); bdrv_set_dirty_tracking(bmds->bs, enable ? BLOCK_SIZE : 0);
} }
} }

17
block.c
View File

@ -2833,6 +2833,8 @@ BlockInfo *bdrv_query_info(BlockDriverState *bs)
info->has_dirty = true; info->has_dirty = true;
info->dirty = g_malloc0(sizeof(*info->dirty)); info->dirty = g_malloc0(sizeof(*info->dirty));
info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE; info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE;
info->dirty->granularity =
((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap));
} }
if (bs->drv) { if (bs->drv) {
@ -4299,16 +4301,17 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
return true; return true;
} }
void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable) void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity)
{ {
int64_t bitmap_size; int64_t bitmap_size;
if (enable) { assert((granularity & (granularity - 1)) == 0);
if (!bs->dirty_bitmap) {
bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS); if (granularity) {
bs->dirty_bitmap = hbitmap_alloc(bitmap_size, granularity >>= BDRV_SECTOR_BITS;
BDRV_LOG_SECTORS_PER_DIRTY_CHUNK); assert(!bs->dirty_bitmap);
} bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
bs->dirty_bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
} else { } else {
if (bs->dirty_bitmap) { if (bs->dirty_bitmap) {
hbitmap_free(bs->dirty_bitmap); hbitmap_free(bs->dirty_bitmap);

View File

@ -17,14 +17,8 @@
#include "qemu/ratelimit.h" #include "qemu/ratelimit.h"
#include "qemu/bitmap.h" #include "qemu/bitmap.h"
enum { #define BLOCK_SIZE (1 << 20)
/* #define BDRV_SECTORS_PER_DIRTY_CHUNK (BLOCK_SIZE >> BDRV_SECTOR_BITS)
* Size of data buffer for populating the image file. This should be large
* enough to process multiple clusters in a single call, so that populating
* contiguous regions of the image is efficient.
*/
BLOCK_SIZE = 512 * BDRV_SECTORS_PER_DIRTY_CHUNK, /* in bytes */
};
#define SLICE_TIME 100000000ULL /* ns */ #define SLICE_TIME 100000000ULL /* ns */
@ -276,7 +270,7 @@ static void coroutine_fn mirror_run(void *opaque)
immediate_exit: immediate_exit:
qemu_vfree(s->buf); qemu_vfree(s->buf);
g_free(s->cow_bitmap); g_free(s->cow_bitmap);
bdrv_set_dirty_tracking(bs, false); bdrv_set_dirty_tracking(bs, 0);
bdrv_iostatus_disable(s->target); bdrv_iostatus_disable(s->target);
if (s->should_complete && ret == 0) { if (s->should_complete && ret == 0) {
if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) { if (bdrv_get_flags(s->target) != bdrv_get_flags(s->common.bs)) {
@ -364,7 +358,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
s->mode = mode; s->mode = mode;
s->buf_size = BLOCK_SIZE; s->buf_size = BLOCK_SIZE;
bdrv_set_dirty_tracking(bs, true); bdrv_set_dirty_tracking(bs, BLOCK_SIZE);
bdrv_set_enable_write_cache(s->target, true); bdrv_set_enable_write_cache(s->target, true);
bdrv_set_on_error(s->target, on_target_error, on_target_error); bdrv_set_on_error(s->target, on_target_error, on_target_error);
bdrv_iostatus_enable(s->target); bdrv_iostatus_enable(s->target);

View File

@ -355,11 +355,8 @@ void bdrv_set_buffer_alignment(BlockDriverState *bs, int align);
void *qemu_blockalign(BlockDriverState *bs, size_t size); void *qemu_blockalign(BlockDriverState *bs, size_t size);
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov); bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
#define BDRV_SECTORS_PER_DIRTY_CHUNK (1 << BDRV_LOG_SECTORS_PER_DIRTY_CHUNK)
#define BDRV_LOG_SECTORS_PER_DIRTY_CHUNK 11
struct HBitmapIter; struct HBitmapIter;
void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable); void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity);
int bdrv_get_dirty(BlockDriverState *bs, int64_t sector); int bdrv_get_dirty(BlockDriverState *bs, int64_t sector);
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); 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); void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);

View File

@ -667,10 +667,12 @@
# #
# @count: number of dirty bytes according to the dirty bitmap # @count: number of dirty bytes according to the dirty bitmap
# #
# @granularity: granularity of the dirty bitmap in bytes (since 1.4)
#
# Since: 1.3 # Since: 1.3
## ##
{ 'type': 'BlockDirtyInfo', { 'type': 'BlockDirtyInfo',
'data': {'count': 'int'} } 'data': {'count': 'int', 'granularity': 'int'} }
## ##
# @BlockInfo: # @BlockInfo: