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:
parent
7f739d0e53
commit
0e2402452f
@ -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 =
|
s->use_copy_range = false;
|
||||||
!(write_flags & BDRV_REQ_WRITE_COMPRESSED) && s->copy_range_size > 0;
|
s->copy_size = cluster_size;
|
||||||
|
} else if (write_flags & BDRV_REQ_WRITE_COMPRESSED) {
|
||||||
|
/* 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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user