block/stream: use BDRV_REQ_PREFETCH

This helps to avoid extra io, allocations and memory copying.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20190725100550.33801-3-vsementsov@virtuozzo.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[eblake: fix comment grammar]
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2019-07-25 13:05:49 +03:00 committed by Eric Blake
parent 3299e5ecf7
commit 99136607b1
1 changed files with 9 additions and 15 deletions

View File

@ -22,11 +22,11 @@
enum { enum {
/* /*
* Size of data buffer for populating the image file. This should be large * Maximum chunk size to feed to copy-on-read. This should be
* enough to process multiple clusters in a single call, so that populating * large enough to process multiple clusters in a single call, so
* contiguous regions of the image is efficient. * that populating contiguous regions of the image is efficient.
*/ */
STREAM_BUFFER_SIZE = 512 * 1024, /* in bytes */ STREAM_CHUNK = 512 * 1024, /* in bytes */
}; };
typedef struct StreamBlockJob { typedef struct StreamBlockJob {
@ -39,13 +39,12 @@ typedef struct StreamBlockJob {
} StreamBlockJob; } StreamBlockJob;
static int coroutine_fn stream_populate(BlockBackend *blk, static int coroutine_fn stream_populate(BlockBackend *blk,
int64_t offset, uint64_t bytes, int64_t offset, uint64_t bytes)
void *buf)
{ {
assert(bytes < SIZE_MAX); assert(bytes < SIZE_MAX);
/* Copy-on-read the unallocated clusters */ return blk_co_preadv(blk, offset, bytes, NULL,
return blk_co_pread(blk, offset, bytes, buf, BDRV_REQ_COPY_ON_READ); BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH);
} }
static void stream_abort(Job *job) static void stream_abort(Job *job)
@ -117,7 +116,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
int error = 0; int error = 0;
int ret = 0; int ret = 0;
int64_t n = 0; /* bytes */ int64_t n = 0; /* bytes */
void *buf;
if (bs == s->bottom) { if (bs == s->bottom) {
/* Nothing to stream */ /* Nothing to stream */
@ -130,8 +128,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
} }
job_progress_set_remaining(&s->common.job, len); job_progress_set_remaining(&s->common.job, len);
buf = qemu_blockalign(bs, STREAM_BUFFER_SIZE);
/* Turn on copy-on-read for the whole block device so that guest read /* Turn on copy-on-read for the whole block device so that guest read
* requests help us make progress. Only do this when copying the entire * requests help us make progress. Only do this when copying the entire
* backing chain since the copy-on-read operation does not take base into * backing chain since the copy-on-read operation does not take base into
@ -154,7 +150,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
copy = false; copy = false;
ret = bdrv_is_allocated(bs, offset, STREAM_BUFFER_SIZE, &n); ret = bdrv_is_allocated(bs, offset, STREAM_CHUNK, &n);
if (ret == 1) { if (ret == 1) {
/* Allocated in the top, no need to copy. */ /* Allocated in the top, no need to copy. */
} else if (ret >= 0) { } else if (ret >= 0) {
@ -171,7 +167,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
} }
trace_stream_one_iteration(s, offset, n, ret); trace_stream_one_iteration(s, offset, n, ret);
if (copy) { if (copy) {
ret = stream_populate(blk, offset, n, buf); ret = stream_populate(blk, offset, n);
} }
if (ret < 0) { if (ret < 0) {
BlockErrorAction action = BlockErrorAction action =
@ -202,8 +198,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
bdrv_disable_copy_on_read(bs); bdrv_disable_copy_on_read(bs);
} }
qemu_vfree(buf);
/* Do not remove the backing file if an error was there but ignored. */ /* Do not remove the backing file if an error was there but ignored. */
return error; return error;
} }