summaryrefslogtreecommitdiff
path: root/block/mirror.c
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2016-07-14 16:33:29 +0300
committerJeff Cody <jcody@redhat.com>2016-07-19 17:02:49 -0400
commit4b5004d9fc5b7d8e4447dc81c2f26477c2d590f7 (patch)
tree6186bb4e9cdaec5f85a732f135368c15ddcaf6b3 /block/mirror.c
parentc7c2769c0e5769eaad9d968fe2161505b657e02a (diff)
downloadqemu-4b5004d9fc5b7d8e4447dc81c2f26477c2d590f7.tar.gz
mirror: improve performance of mirroring of empty disk
We should not take into account zero blocks for delay calculations. They are not read and thus IO throttling is not required. In the other case VM migration with 16 Tb QCOW2 disk with 4 Gb of data takes days. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Fam Zheng <famz@redhat.com> Message-id: 1468503209-19498-9-git-send-email-den@openvz.org CC: Stefan Hajnoczi <stefanha@redhat.com> CC: Kevin Wolf <kwolf@redhat.com> CC: Max Reitz <mreitz@redhat.com> CC: Jeff Cody <jcody@redhat.com> CC: Eric Blake <eblake@redhat.com> Signed-off-by: Jeff Cody <jcody@redhat.com>
Diffstat (limited to 'block/mirror.c')
-rw-r--r--block/mirror.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/block/mirror.c b/block/mirror.c
index 0262b03989..f78186d47b 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -323,6 +323,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
int nb_chunks = 1;
int64_t end = s->bdev_length / BDRV_SECTOR_SIZE;
int sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
+ bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target));
sector_num = hbitmap_iter_next(&s->hbi);
if (sector_num < 0) {
@@ -373,7 +374,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
bitmap_set(s->in_flight_bitmap, sector_num / sectors_per_chunk, nb_chunks);
while (nb_chunks > 0 && sector_num < end) {
int ret;
- int io_sectors;
+ int io_sectors, io_sectors_acct;
BlockDriverState *file;
enum MirrorMethod {
MIRROR_METHOD_COPY,
@@ -410,12 +411,17 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
switch (mirror_method) {
case MIRROR_METHOD_COPY:
io_sectors = mirror_do_read(s, sector_num, io_sectors);
+ io_sectors_acct = io_sectors;
break;
case MIRROR_METHOD_ZERO:
- mirror_do_zero_or_discard(s, sector_num, io_sectors, false);
- break;
case MIRROR_METHOD_DISCARD:
- mirror_do_zero_or_discard(s, sector_num, io_sectors, true);
+ mirror_do_zero_or_discard(s, sector_num, io_sectors,
+ mirror_method == MIRROR_METHOD_DISCARD);
+ if (write_zeroes_ok) {
+ io_sectors_acct = 0;
+ } else {
+ io_sectors_acct = io_sectors;
+ }
break;
default:
abort();
@@ -424,7 +430,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
sector_num += io_sectors;
nb_chunks -= DIV_ROUND_UP(io_sectors, sectors_per_chunk);
if (s->common.speed) {
- delay_ns = ratelimit_calculate_delay(&s->limit, io_sectors);
+ delay_ns = ratelimit_calculate_delay(&s->limit, io_sectors_acct);
}
}
return delay_ns;