block/block-copy: increase buffered copy request

No reason to limit buffered copy to one cluster. Let's allow up to 1
MiB.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: 20191022111805.3432-7-vsementsov@virtuozzo.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2019-10-22 14:18:05 +03:00 committed by Max Reitz
parent 7f739d0e53
commit 0e2402452f
2 changed files with 33 additions and 17 deletions

View File

@ -21,6 +21,7 @@
#include "qemu/units.h" #include "qemu/units.h"
#define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB) #define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB)
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
#define BLOCK_COPY_MAX_MEM (128 * MiB) #define BLOCK_COPY_MAX_MEM (128 * MiB)
static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s, static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s,
@ -75,10 +76,8 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
{ {
BlockCopyState *s; BlockCopyState *s;
BdrvDirtyBitmap *copy_bitmap; BdrvDirtyBitmap *copy_bitmap;
/* Ignore BLOCK_COPY_MAX_COPY_RANGE if requested cluster_size is larger */
uint32_t max_transfer = uint32_t max_transfer =
MIN_NON_ZERO(MAX(cluster_size, BLOCK_COPY_MAX_COPY_RANGE), MIN_NON_ZERO(INT_MAX,
MIN_NON_ZERO(source->bs->bl.max_transfer, MIN_NON_ZERO(source->bs->bl.max_transfer,
target->bs->bl.max_transfer)); target->bs->bl.max_transfer));
@ -100,17 +99,28 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
.mem = shres_create(BLOCK_COPY_MAX_MEM), .mem = shres_create(BLOCK_COPY_MAX_MEM),
}; };
s->copy_range_size = QEMU_ALIGN_DOWN(max_transfer, cluster_size), if (max_transfer < cluster_size) {
/* /*
* Set use_copy_range, consider the following: * copy_range does not respect max_transfer. We don't want to bother
* 1. Compression is not supported for copy_range. * with requests smaller than block-copy cluster size, so fallback to
* 2. copy_range does not respect max_transfer (it's a TODO), so we factor * buffered copying (read and write respect max_transfer on their
* that in here. If max_transfer is smaller than the job->cluster_size, * behalf).
* we do not use copy_range (in that case it's zero after aligning down */
* above). s->use_copy_range = false;
*/ s->copy_size = cluster_size;
s->use_copy_range = } else if (write_flags & BDRV_REQ_WRITE_COMPRESSED) {
!(write_flags & BDRV_REQ_WRITE_COMPRESSED) && s->copy_range_size > 0; /* Compression is not supported for copy_range */
s->use_copy_range = false;
s->copy_size = MAX(cluster_size, BLOCK_COPY_MAX_BUFFER);
} else {
/*
* copy_range does not respect max_transfer (it's a TODO), so we factor
* that in here.
*/
s->use_copy_range = true;
s->copy_size = MIN(MAX(cluster_size, BLOCK_COPY_MAX_COPY_RANGE),
QEMU_ALIGN_DOWN(max_transfer, cluster_size));
}
QLIST_INIT(&s->inflight_reqs); QLIST_INIT(&s->inflight_reqs);
@ -156,12 +166,19 @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
if (ret < 0) { if (ret < 0) {
trace_block_copy_copy_range_fail(s, start, ret); trace_block_copy_copy_range_fail(s, start, ret);
s->use_copy_range = false; s->use_copy_range = false;
s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
/* Fallback to read+write with allocated buffer */ /* Fallback to read+write with allocated buffer */
} else { } else {
goto out; goto out;
} }
} }
/*
* In case of failed copy_range request above, we may proceed with buffered
* request larger than BLOCK_COPY_MAX_BUFFER. Still, further requests will
* be properly limited, so don't care too much.
*/
bounce_buffer = qemu_blockalign(s->source->bs, nbytes); bounce_buffer = qemu_blockalign(s->source->bs, nbytes);
ret = bdrv_co_pread(s->source, start, nbytes, bounce_buffer, 0); ret = bdrv_co_pread(s->source, start, nbytes, bounce_buffer, 0);
@ -290,8 +307,7 @@ int coroutine_fn block_copy(BlockCopyState *s,
continue; /* already copied */ continue; /* already copied */
} }
chunk_end = MIN(end, start + (s->use_copy_range ? chunk_end = MIN(end, start + s->copy_size);
s->copy_range_size : s->cluster_size));
next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start, next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start,
chunk_end - start); chunk_end - start);

View File

@ -38,7 +38,7 @@ typedef struct BlockCopyState {
BdrvDirtyBitmap *copy_bitmap; BdrvDirtyBitmap *copy_bitmap;
int64_t cluster_size; int64_t cluster_size;
bool use_copy_range; bool use_copy_range;
int64_t copy_range_size; int64_t copy_size;
uint64_t len; uint64_t len;
QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs; QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs;