We have replaced the mechanics of syncing new writes in the previous patch and thus do not need to track dirty changes anymore.
Signed-off-by: Denis V. Lunev <d...@openvz.org> Reviewed-by: Vladimir Sementsov-Ogievskiy<vsement...@virtuozzo.com> CC: Stefan Hajnoczi <stefa...@redhat.com> CC: Fam Zheng <f...@redhat.com> CC: Kevin Wolf <kw...@redhat.com> CC: Max Reitz <mre...@redhat.com> CC: Jeff Cody <jc...@redhat.com> CC: Eric Blake <ebl...@redhat.com> --- block/mirror.c | 58 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 086256c..926fd13 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -52,7 +52,7 @@ typedef struct MirrorBlockJob { size_t buf_size; int64_t bdev_length; unsigned long *cow_bitmap; - BdrvDirtyBitmap *dirty_bitmap; + HBitmap *copy_bitmap; HBitmapIter hbi; uint8_t *buf; QSIMPLEQ_HEAD(, MirrorBuffer) buf_free; @@ -141,7 +141,7 @@ static void mirror_write_complete(void *opaque, int ret) if (ret < 0) { BlockErrorAction action; - bdrv_set_dirty_bitmap(s->dirty_bitmap, op->sector_num, op->nb_sectors); + hbitmap_set(s->copy_bitmap, op->sector_num, op->nb_sectors); action = mirror_error_action(s, false, -ret); if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) { s->ret = ret; @@ -157,7 +157,7 @@ static void mirror_read_complete(void *opaque, int ret) if (ret < 0) { BlockErrorAction action; - bdrv_set_dirty_bitmap(s->dirty_bitmap, op->sector_num, op->nb_sectors); + hbitmap_set(s->copy_bitmap, op->sector_num, op->nb_sectors); action = mirror_error_action(s, true, -ret); if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) { s->ret = ret; @@ -328,9 +328,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) sector_num = hbitmap_iter_next(&s->hbi); if (sector_num < 0) { - bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi); + hbitmap_iter_init(&s->hbi, s->copy_bitmap, 0); sector_num = hbitmap_iter_next(&s->hbi); - trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap)); + trace_mirror_restart_iter(s, hbitmap_count(s->copy_bitmap)); assert(sector_num >= 0); } @@ -347,7 +347,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) int64_t next_sector = sector_num + nb_chunks * sectors_per_chunk; int64_t next_chunk = next_sector / sectors_per_chunk; if (next_sector >= end || - !bdrv_get_dirty(source, s->dirty_bitmap, next_sector)) { + !hbitmap_get(s->copy_bitmap, next_sector)) { break; } if (test_bit(next_chunk, s->in_flight_bitmap)) { @@ -357,7 +357,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) hbitmap_next = hbitmap_iter_next(&s->hbi); if (hbitmap_next > next_sector || hbitmap_next < 0) { /* The bitmap iterator's cache is stale, refresh it */ - bdrv_set_dirty_iter(&s->hbi, next_sector); + hbitmap_iter_init(&s->hbi, s->copy_bitmap, next_sector); hbitmap_next = hbitmap_iter_next(&s->hbi); } assert(hbitmap_next == next_sector); @@ -368,8 +368,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) * calling bdrv_get_block_status_above could yield - if some blocks are * marked dirty in this window, we need to know. */ - bdrv_reset_dirty_bitmap(s->dirty_bitmap, sector_num, - nb_chunks * sectors_per_chunk); + hbitmap_reset(s->copy_bitmap, sector_num, nb_chunks * sectors_per_chunk); bitmap_set(s->in_flight_bitmap, sector_num / sectors_per_chunk, nb_chunks); while (nb_chunks > 0 && sector_num < end) { int ret; @@ -553,8 +552,8 @@ static int coroutine_fn mirror_before_write_notify( aligned_start = QEMU_ALIGN_UP(sector_num, sectors_per_chunk); aligned_end = QEMU_ALIGN_DOWN(sector_num + nb_sectors, sectors_per_chunk); if (aligned_end > aligned_start) { - bdrv_reset_dirty_bitmap(s->dirty_bitmap, aligned_start, - aligned_end - aligned_start); + hbitmap_reset(s->copy_bitmap, aligned_start, + aligned_end - aligned_start); } if (req->type == BDRV_TRACKED_DISCARD) { @@ -596,7 +595,7 @@ static int mirror_dirty_init(MirrorBlockJob *s) if (base == NULL && !bdrv_has_zero_init(target_bs) && target_bs->drv->bdrv_co_write_zeroes == NULL) { - bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, end); + hbitmap_set(s->copy_bitmap, 0, end); return 0; } @@ -625,7 +624,7 @@ static int mirror_dirty_init(MirrorBlockJob *s) assert(n > 0); if (ret == 1) { - bdrv_set_dirty_bitmap(s->dirty_bitmap, sector_num, n); + hbitmap_set(s->copy_bitmap, sector_num, n); } sector_num += n; } @@ -729,7 +728,7 @@ static void coroutine_fn mirror_run(void *opaque) } last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi); + hbitmap_iter_init(&s->hbi, s->copy_bitmap, 0); for (;;) { uint64_t delay_ns = 0; int64_t cnt; @@ -740,7 +739,7 @@ static void coroutine_fn mirror_run(void *opaque) goto immediate_exit; } - cnt = bdrv_get_dirty_count(s->dirty_bitmap); + cnt = hbitmap_count(s->copy_bitmap); /* s->common.offset contains the number of bytes already processed so * far, cnt is the number of dirty sectors remaining and * s->sectors_in_flight is the number of sectors currently being @@ -787,7 +786,7 @@ static void coroutine_fn mirror_run(void *opaque) should_complete = s->should_complete || block_job_is_cancelled(&s->common); - cnt = bdrv_get_dirty_count(s->dirty_bitmap); + cnt = hbitmap_count(s->copy_bitmap); } } @@ -802,7 +801,7 @@ static void coroutine_fn mirror_run(void *opaque) */ trace_mirror_before_drain(s, cnt); bdrv_co_drain(bs); - cnt = bdrv_get_dirty_count(s->dirty_bitmap); + cnt = hbitmap_count(s->copy_bitmap); } ret = 0; @@ -842,7 +841,7 @@ immediate_exit: qemu_vfree(s->buf); g_free(s->cow_bitmap); g_free(s->in_flight_bitmap); - bdrv_release_dirty_bitmap(bs, s->dirty_bitmap); + hbitmap_free(s->copy_bitmap); data = g_malloc(sizeof(*data)); data->ret = ret; @@ -925,6 +924,25 @@ static const BlockJobDriver commit_active_job_driver = { .complete = mirror_complete, }; +static HBitmap *mirror_create_bitmap(BlockDriverState *bs, + uint32_t granularity, Error **errp) +{ + int64_t bitmap_size; + uint32_t sector_granularity; + + assert((granularity & (granularity - 1)) == 0); + + sector_granularity = granularity >> BDRV_SECTOR_BITS; + assert(sector_granularity); + bitmap_size = bdrv_nb_sectors(bs); + if (bitmap_size < 0) { + error_setg_errno(errp, -bitmap_size, "could not get length of device"); + errno = -bitmap_size; + return NULL; + } + return hbitmap_alloc(bitmap_size, ctz32(sector_granularity)); +} + static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, const char *replaces, int64_t speed, uint32_t granularity, @@ -971,8 +989,8 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, s->buf_size = ROUND_UP(buf_size, granularity); s->unmap = unmap; - s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); - if (!s->dirty_bitmap) { + s->copy_bitmap = mirror_create_bitmap(bs, granularity, errp); + if (s->copy_bitmap == NULL) { g_free(s->replaces); blk_unref(s->target); block_job_unref(&s->common); -- 2.5.0