static int coroutine_fn do_perform_cow(BlockDriverState *bs,

                                       uint64_t src_cluster_offset,

                                       uint64_t cluster_offset,

                                       int offset_in_cluster,

                                       int bytes)

{

    BDRVQcow2State *s = bs->opaque;

    QEMUIOVector qiov;

    struct iovec iov;

    int ret;



    iov.iov_len = bytes;

    iov.iov_base = qemu_try_blockalign(bs, iov.iov_len);

    if (iov.iov_base == NULL) {

        return -ENOMEM;

    }



    qemu_iovec_init_external(&qiov, &iov, 1);



    BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);



    if (!bs->drv) {

        ret = -ENOMEDIUM;

        goto out;

    }



    /* Call .bdrv_co_readv() directly instead of using the public block-layer

     * interface.  This avoids double I/O throttling and request tracking,

     * which can lead to deadlock when block layer copy-on-read is enabled.

     */

    ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,

                                  bytes, &qiov, 0);

    if (ret < 0) {

        goto out;

    }



    if (bs->encrypted) {

        Error *err = NULL;

        int64_t sector = (cluster_offset + offset_in_cluster)

                         >> BDRV_SECTOR_BITS;

        assert(s->cipher);

        assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);

        assert((bytes & ~BDRV_SECTOR_MASK) == 0);

        if (qcow2_encrypt_sectors(s, sector, iov.iov_base, iov.iov_base,

                                  bytes >> BDRV_SECTOR_BITS, true, &err) < 0) {

            ret = -EIO;

            error_free(err);

            goto out;

        }

    }



    ret = qcow2_pre_write_overlap_check(bs, 0,

            cluster_offset + offset_in_cluster, bytes);

    if (ret < 0) {

        goto out;

    }



    BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);

    ret = bdrv_co_pwritev(bs->file->bs, cluster_offset + offset_in_cluster,

                          bytes, &qiov, 0);

    if (ret < 0) {

        goto out;

    }



    ret = 0;

out:

    qemu_vfree(iov.iov_base);

    return ret;

}

static int coroutine_fn do_perform_cow(BlockDriverState *bs,

                                       uint64_t src_cluster_offset,

                                       uint64_t cluster_offset,

                                       int offset_in_cluster,

                                       int bytes)

{

    BDRVQcow2State *s = bs->opaque;

    QEMUIOVector qiov;

    struct iovec iov;

    int ret;



    iov.iov_len = bytes;

    iov.iov_base = qemu_try_blockalign(bs, iov.iov_len);

    if (iov.iov_base == NULL) {

        return -ENOMEM;

    }



    qemu_iovec_init_external(&qiov, &iov, 1);



    BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);



    if (!bs->drv) {

        ret = -ENOMEDIUM;

        goto out;

    }



    







    ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,

                                  bytes, &qiov, 0);

    if (ret < 0) {

        goto out;

    }



    if (bs->encrypted) {

        Error *err = NULL;

        int64_t sector = (cluster_offset + offset_in_cluster)

                         >> BDRV_SECTOR_BITS;

        assert(s->cipher);

        assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);

        assert((bytes & ~BDRV_SECTOR_MASK) == 0);

        if (qcow2_encrypt_sectors(s, sector, iov.iov_base, iov.iov_base,

                                  bytes >> BDRV_SECTOR_BITS, true, &err) < 0) {

            ret = -EIO;

            error_free(err);

            goto out;

        }

    }



    ret = qcow2_pre_write_overlap_check(bs, 0,

            cluster_offset + offset_in_cluster, bytes);

    if (ret < 0) {

        goto out;

    }



    BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);

    ret = bdrv_co_pwritev(bs->file->bs, cluster_offset + offset_in_cluster,

                          bytes, &qiov, 0);

    if (ret < 0) {

        goto out;

    }



    ret = 0;

out:

    qemu_vfree(iov.iov_base);

    return ret;

}

static int VAR_0 do_perform_cow(BlockDriverState *bs,

                                       uint64_t src_cluster_offset,

                                       uint64_t cluster_offset,

                                       int offset_in_cluster,

                                       int bytes)

{

    BDRVQcow2State *s = bs->opaque;

    QEMUIOVector qiov;

    struct iovec iov;

    int ret;



    iov.iov_len = bytes;

    iov.iov_base = qemu_try_blockalign(bs, iov.iov_len);

    if (iov.iov_base == NULL) {

        return -ENOMEM;

    }



    qemu_iovec_init_external(&qiov, &iov, 1);



    BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);



    if (!bs->drv) {

        ret = -ENOMEDIUM;

        goto out;

    }



    







    ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,

                                  bytes, &qiov, 0);

    if (ret < 0) {

        goto out;

    }



    if (bs->encrypted) {

        Error *err = NULL;

        int64_t sector = (cluster_offset + offset_in_cluster)

                         >> BDRV_SECTOR_BITS;

        assert(s->cipher);

        assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);

        assert((bytes & ~BDRV_SECTOR_MASK) == 0);

        if (qcow2_encrypt_sectors(s, sector, iov.iov_base, iov.iov_base,

                                  bytes >> BDRV_SECTOR_BITS, true, &err) < 0) {

            ret = -EIO;

            error_free(err);

            goto out;

        }

    }



    ret = qcow2_pre_write_overlap_check(bs, 0,

            cluster_offset + offset_in_cluster, bytes);

    if (ret < 0) {

        goto out;

    }



    BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);

    ret = bdrv_co_pwritev(bs->file->bs, cluster_offset + offset_in_cluster,

                          bytes, &qiov, 0);

    if (ret < 0) {

        goto out;

    }



    ret = 0;

out:

    qemu_vfree(iov.iov_base);

    return ret;

}

static int VAR_0 do_perform_cow(BlockDriverState *bs,
uint64_t src_cluster_offset,
uint64_t cluster_offset,
int offset_in_cluster,
int bytes)
{ BDRVQcow2State *s = bs->opaque; QEMUIOVector qiov; struct iovec iov; int ret; iov.iov_len = bytes; iov.iov_base = qemu_try_blockalign(bs, iov.iov_len); if (iov.iov_base == NULL) { return -ENOMEM; } qemu_iovec_init_external(&qiov, &iov, 1); BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); if (!bs->drv) { ret = -ENOMEDIUM; goto out; } ret = bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_cluster,
bytes, &qiov, 0); if (ret < 0) { goto out; } if (bs->encrypted) { Error *err = NULL; int64_t sector = (cluster_offset + offset_in_cluster)
>> BDRV_SECTOR_BITS; assert(s->cipher); assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0); assert((bytes & ~BDRV_SECTOR_MASK) == 0); if (qcow2_encrypt_sectors(s, sector, iov.iov_base, iov.iov_base,
bytes >> BDRV_SECTOR_BITS, true, &err) < 0) { ret = -EIO; error_free(err); goto out; } } ret = qcow2_pre_write_overlap_check(bs, 0,
cluster_offset + offset_in_cluster, bytes); if (ret < 0) { goto out; } BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); ret = bdrv_co_pwritev(bs->file->bs, cluster_offset + offset_in_cluster,
bytes, &qiov, 0); if (ret < 0) { goto out; } ret = 0; out:
qemu_vfree(iov.iov_base); return ret; }