Commit ac850bf0 authored by Vladimir Sementsov-Ogievskiy's avatar Vladimir Sementsov-Ogievskiy Committed by Stefan Hajnoczi
Browse files

block: define .*_part io handlers in BlockDriver



Add handlers supporting qiov_offset parameter:
    bdrv_co_preadv_part
    bdrv_co_pwritev_part
    bdrv_co_pwritev_compressed_part
This is used to reduce need of defining local_qiovs and hd_qiovs in all
corners of block layer code. The following patches will increase usage
of this new API part by part.

Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Acked-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Message-id: 20190604161514.262241-5-vsementsov@virtuozzo.com
Message-Id: <20190604161514.262241-5-vsementsov@virtuozzo.com>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent 7a3f542f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -674,7 +674,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
        return NULL;
    }

    if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
    if (compress && !block_driver_can_compress(target->drv)) {
        error_setg(errp, "Compression is not supported for this drive %s",
                   bdrv_get_device_name(target));
        return NULL;
+77 −19
Original line number Diff line number Diff line
@@ -146,7 +146,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)

    /* Default alignment based on whether driver has byte interface */
    bs->bl.request_alignment = (drv->bdrv_co_preadv ||
                                drv->bdrv_aio_preadv) ? 1 : 512;
                                drv->bdrv_aio_preadv ||
                                drv->bdrv_co_preadv_part) ? 1 : 512;

    /* Take some limits from the children as a default */
    if (bs->file) {
@@ -1044,11 +1045,14 @@ static void bdrv_co_io_em_complete(void *opaque, int ret)

static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
                                           uint64_t offset, uint64_t bytes,
                                           QEMUIOVector *qiov, int flags)
                                           QEMUIOVector *qiov,
                                           size_t qiov_offset, int flags)
{
    BlockDriver *drv = bs->drv;
    int64_t sector_num;
    unsigned int nb_sectors;
    QEMUIOVector local_qiov;
    int ret;

    assert(!(flags & ~BDRV_REQ_MASK));
    assert(!(flags & BDRV_REQ_NO_FALLBACK));
@@ -1057,8 +1061,19 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
        return -ENOMEDIUM;
    }

    if (drv->bdrv_co_preadv_part) {
        return drv->bdrv_co_preadv_part(bs, offset, bytes, qiov, qiov_offset,
                                        flags);
    }

    if (qiov_offset > 0 || bytes != qiov->size) {
        qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
        qiov = &local_qiov;
    }

    if (drv->bdrv_co_preadv) {
        return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
        ret = drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
        goto out;
    }

    if (drv->bdrv_aio_preadv) {
@@ -1070,10 +1085,12 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
        acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
                                   bdrv_co_io_em_complete, &co);
        if (acb == NULL) {
            return -EIO;
            ret = -EIO;
            goto out;
        } else {
            qemu_coroutine_yield();
            return co.ret;
            ret = co.ret;
            goto out;
        }
    }

@@ -1085,16 +1102,25 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
    assert(bytes <= BDRV_REQUEST_MAX_BYTES);
    assert(drv->bdrv_co_readv);

    return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
    ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);

out:
    if (qiov == &local_qiov) {
        qemu_iovec_destroy(&local_qiov);
    }

    return ret;
}

static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
                                            uint64_t offset, uint64_t bytes,
                                            QEMUIOVector *qiov, int flags)
                                            QEMUIOVector *qiov,
                                            size_t qiov_offset, int flags)
{
    BlockDriver *drv = bs->drv;
    int64_t sector_num;
    unsigned int nb_sectors;
    QEMUIOVector local_qiov;
    int ret;

    assert(!(flags & ~BDRV_REQ_MASK));
@@ -1104,6 +1130,18 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
        return -ENOMEDIUM;
    }

    if (drv->bdrv_co_pwritev_part) {
        ret = drv->bdrv_co_pwritev_part(bs, offset, bytes, qiov, qiov_offset,
                                        flags & bs->supported_write_flags);
        flags &= ~bs->supported_write_flags;
        goto emulate_flags;
    }

    if (qiov_offset > 0 || bytes != qiov->size) {
        qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
        qiov = &local_qiov;
    }

    if (drv->bdrv_co_pwritev) {
        ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov,
                                   flags & bs->supported_write_flags);
@@ -1147,26 +1185,46 @@ emulate_flags:
        ret = bdrv_co_flush(bs);
    }

    if (qiov == &local_qiov) {
        qemu_iovec_destroy(&local_qiov);
    }

    return ret;
}

static int coroutine_fn
bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
                               uint64_t bytes, QEMUIOVector *qiov)
                               uint64_t bytes, QEMUIOVector *qiov,
                               size_t qiov_offset)
{
    BlockDriver *drv = bs->drv;
    QEMUIOVector local_qiov;
    int ret;

    if (!drv) {
        return -ENOMEDIUM;
    }

    if (!drv->bdrv_co_pwritev_compressed) {
    if (!block_driver_can_compress(drv)) {
        return -ENOTSUP;
    }

    if (drv->bdrv_co_pwritev_compressed_part) {
        return drv->bdrv_co_pwritev_compressed_part(bs, offset, bytes,
                                                    qiov, qiov_offset);
    }

    if (qiov_offset == 0) {
        return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
    }

    qemu_iovec_init_slice(&local_qiov, qiov, qiov_offset, bytes);
    ret = drv->bdrv_co_pwritev_compressed(bs, offset, bytes, &local_qiov);
    qemu_iovec_destroy(&local_qiov);

    return ret;
}

static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
        int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
        int flags)
@@ -1249,7 +1307,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
            qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);

            ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
                                     &local_qiov, 0);
                                     &local_qiov, 0, 0);
            if (ret < 0) {
                goto err;
            }
@@ -1267,7 +1325,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
                 * necessary to flush even in cache=writethrough mode.
                 */
                ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
                                          &local_qiov,
                                          &local_qiov, 0,
                                          BDRV_REQ_WRITE_UNCHANGED);
            }

@@ -1289,7 +1347,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
            qemu_iovec_init(&local_qiov, qiov->niov);
            qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes);
            ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size,
                                     &local_qiov, 0);
                                     &local_qiov, 0, 0);
            qemu_iovec_destroy(&local_qiov);
            if (ret < 0) {
                goto err;
@@ -1380,7 +1438,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,

    max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
    if (bytes <= max_bytes && bytes <= max_transfer) {
        ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0);
        ret = bdrv_driver_preadv(bs, offset, bytes, qiov, 0, 0);
        goto out;
    }

@@ -1396,7 +1454,7 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
            qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);

            ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining,
                                     num, &local_qiov, 0);
                                     num, &local_qiov, 0, 0);
            max_bytes -= num;
            qemu_iovec_destroy(&local_qiov);
        } else {
@@ -1701,7 +1759,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
            }
            qemu_iovec_init_buf(&qiov, buf, num);

            ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags);
            ret = bdrv_driver_pwritev(bs, offset, num, &qiov, 0, write_flags);

            /* Keep bounce buffer around if it is big enough for all
             * all future requests.
@@ -1857,10 +1915,10 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
        bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
        ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
    } else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
        ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov);
        ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov, 0);
    } else if (bytes <= max_transfer) {
        bdrv_debug_event(bs, BLKDBG_PWRITEV);
        ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
        ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, 0, flags);
    } else {
        bdrv_debug_event(bs, BLKDBG_PWRITEV);
        while (bytes_remaining) {
@@ -1879,7 +1937,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
            qemu_iovec_concat(&local_qiov, qiov, bytes - bytes_remaining, num);

            ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining,
                                      num, &local_qiov, local_flags);
                                      num, &local_qiov, 0, local_flags);
            qemu_iovec_destroy(&local_qiov);
            if (ret < 0) {
                break;
+15 −0
Original line number Diff line number Diff line
@@ -210,6 +210,9 @@ struct BlockDriver {
     */
    int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
        uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
    int coroutine_fn (*bdrv_co_preadv_part)(BlockDriverState *bs,
        uint64_t offset, uint64_t bytes,
        QEMUIOVector *qiov, size_t qiov_offset, int flags);
    int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags);
    /**
@@ -229,6 +232,9 @@ struct BlockDriver {
     */
    int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs,
        uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
    int coroutine_fn (*bdrv_co_pwritev_part)(BlockDriverState *bs,
        uint64_t offset, uint64_t bytes,
        QEMUIOVector *qiov, size_t qiov_offset, int flags);

    /*
     * Efficiently zero a region of the disk image.  Typically an image format
@@ -339,6 +345,9 @@ struct BlockDriver {

    int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs,
        uint64_t offset, uint64_t bytes, QEMUIOVector *qiov);
    int coroutine_fn (*bdrv_co_pwritev_compressed_part)(BlockDriverState *bs,
        uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
        size_t qiov_offset);

    int (*bdrv_snapshot_create)(BlockDriverState *bs,
                                QEMUSnapshotInfo *sn_info);
@@ -570,6 +579,12 @@ struct BlockDriver {
    const char *const *strong_runtime_opts;
};

static inline bool block_driver_can_compress(BlockDriver *drv)
{
    return drv->bdrv_co_pwritev_compressed ||
           drv->bdrv_co_pwritev_compressed_part;
}

typedef struct BlockLimits {
    /* Alignment requirement, in bytes, for offset/length of I/O
     * requests. Must be a power of 2 less than INT_MAX; defaults to
+2 −2
Original line number Diff line number Diff line
@@ -2388,7 +2388,7 @@ static int img_convert(int argc, char **argv)
        const char *preallocation =
            qemu_opt_get(opts, BLOCK_OPT_PREALLOC);

        if (drv && !drv->bdrv_co_pwritev_compressed) {
        if (drv && !block_driver_can_compress(drv)) {
            error_report("Compression not supported for this file format");
            ret = -1;
            goto out;
@@ -2459,7 +2459,7 @@ static int img_convert(int argc, char **argv)
    }
    out_bs = blk_bs(s.target);

    if (s.compressed && !out_bs->drv->bdrv_co_pwritev_compressed) {
    if (s.compressed && !block_driver_can_compress(out_bs->drv)) {
        error_report("Compression not supported for this file format");
        ret = -1;
        goto out;