Commit 99136607 authored by Vladimir Sementsov-Ogievskiy's avatar Vladimir Sementsov-Ogievskiy Committed by Eric Blake
Browse files

block/stream: use BDRV_REQ_PREFETCH



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

Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20190725100550.33801-3-vsementsov@virtuozzo.com>
Reviewed-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
[eblake: fix comment grammar]
Signed-off-by: default avatarEric Blake <eblake@redhat.com>
parent 3299e5ec
Loading
Loading
Loading
Loading
+9 −15
Original line number Diff line number Diff line
@@ -22,11 +22,11 @@

enum {
    /*
     * Size of data buffer for populating the image file.  This should be large
     * enough to process multiple clusters in a single call, so that populating
     * contiguous regions of the image is efficient.
     * Maximum chunk size to feed to copy-on-read.  This should be
     * large enough to process multiple clusters in a single call, so
     * 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 {
@@ -39,13 +39,12 @@ typedef struct StreamBlockJob {
} StreamBlockJob;

static int coroutine_fn stream_populate(BlockBackend *blk,
                                        int64_t offset, uint64_t bytes,
                                        void *buf)
                                        int64_t offset, uint64_t bytes)
{
    assert(bytes < SIZE_MAX);

    /* Copy-on-read the unallocated clusters */
    return blk_co_pread(blk, offset, bytes, buf, BDRV_REQ_COPY_ON_READ);
    return blk_co_preadv(blk, offset, bytes, NULL,
                         BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH);
}

static void stream_abort(Job *job)
@@ -117,7 +116,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
    int error = 0;
    int ret = 0;
    int64_t n = 0; /* bytes */
    void *buf;

    if (bs == s->bottom) {
        /* 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);

    buf = qemu_blockalign(bs, STREAM_BUFFER_SIZE);

    /* 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
     * 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;

        ret = bdrv_is_allocated(bs, offset, STREAM_BUFFER_SIZE, &n);
        ret = bdrv_is_allocated(bs, offset, STREAM_CHUNK, &n);
        if (ret == 1) {
            /* Allocated in the top, no need to copy.  */
        } 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);
        if (copy) {
            ret = stream_populate(blk, offset, n, buf);
            ret = stream_populate(blk, offset, n);
        }
        if (ret < 0) {
            BlockErrorAction action =
@@ -202,8 +198,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp)
        bdrv_disable_copy_on_read(bs);
    }

    qemu_vfree(buf);

    /* Do not remove the backing file if an error was there but ignored. */
    return error;
}