Commit bcbb3866 authored by Edgar Kaziakhmedov's avatar Edgar Kaziakhmedov Committed by Stefan Hajnoczi
Browse files

block/parallels: add backing support to readv/writev



Since parallels format supports backing files, refine
readv/writev (allocate_clusters) to redirect read/write requests
to a backing file (if cluster is not available in the current bs).

Signed-off-by: default avatarEdgar Kaziakhmedov <edgar.kaziakhmedov@virtuozzo.com>
Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: default avatarDenis V. Lunev <den@openvz.org>
Signed-off-by: default avatarKlim Kireev <klim.kireev@virtuozzo.com>
Message-id: 20180112090122.1702-6-klim.kireev@virtuozzo.com
CC: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent 908b1c84
Loading
Loading
Loading
Loading
+44 −6
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
                                 int nb_sectors, int *pnum)
{
    int ret;
    BDRVParallelsState *s = bs->opaque;
    int64_t pos, space, idx, to_allocate, i, len;

@@ -170,7 +171,6 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
        return len;
    }
    if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) {
        int ret;
        space += s->prealloc_size;
        if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
            ret = bdrv_pwrite_zeroes(bs->file,
@@ -186,6 +186,37 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
        }
    }

    /* Try to read from backing to fill empty clusters
     * FIXME: 1. previous write_zeroes may be redundant
     *        2. most of data we read from backing will be rewritten by
     *           parallels_co_writev. On aligned-to-cluster write we do not need
     *           this read at all.
     *        3. it would be good to combine write of data from backing and new
     *           data into one write call */
    if (bs->backing) {
        int64_t nb_cow_sectors = to_allocate * s->tracks;
        int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
        QEMUIOVector qiov;
        struct iovec iov = {
            .iov_len = nb_cow_bytes,
            .iov_base = qemu_blockalign(bs, nb_cow_bytes)
        };
        qemu_iovec_init_external(&qiov, &iov, 1);

        ret = bdrv_co_readv(bs->backing, idx * s->tracks, nb_cow_sectors,
                            &qiov);
        if (ret < 0) {
            qemu_vfree(iov.iov_base);
            return ret;
        }

        ret = bdrv_co_writev(bs->file, s->data_end, nb_cow_sectors, &qiov);
        qemu_vfree(iov.iov_base);
        if (ret < 0) {
            return ret;
        }
    }

    for (i = 0; i < to_allocate; i++) {
        s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
        s->data_end += s->tracks;
@@ -309,12 +340,19 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,

        nbytes = n << BDRV_SECTOR_BITS;

        if (position < 0) {
            qemu_iovec_memset(qiov, bytes_done, 0, nbytes);
        } else {
        qemu_iovec_reset(&hd_qiov);
        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);

        if (position < 0) {
            if (bs->backing) {
                ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
                if (ret < 0) {
                    break;
                }
            } else {
                qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
            }
        } else {
            ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
            if (ret < 0) {
                break;
@@ -748,7 +786,7 @@ static BlockDriver bdrv_parallels = {
    .bdrv_co_flush_to_os      = parallels_co_flush_to_os,
    .bdrv_co_readv  = parallels_co_readv,
    .bdrv_co_writev = parallels_co_writev,

    .supports_backing = true,
    .bdrv_create    = parallels_create,
    .bdrv_check     = parallels_check,
    .create_opts    = &parallels_create_opts,