static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,

                                         uint64_t bytes, QEMUIOVector *qiov,

                                         int flags)

{

    BDRVQcow2State *s = bs->opaque;

    int offset_in_cluster;

    int ret;

    unsigned int cur_bytes; /* number of sectors in current iteration */

    uint64_t cluster_offset;

    QEMUIOVector hd_qiov;

    uint64_t bytes_done = 0;

    uint8_t *cluster_data = NULL;

    QCowL2Meta *l2meta = NULL;



    trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);



    qemu_iovec_init(&hd_qiov, qiov->niov);



    s->cluster_cache_offset = -1; /* disable compressed cache */



    qemu_co_mutex_lock(&s->lock);



    while (bytes != 0) {



        l2meta = NULL;



        trace_qcow2_writev_start_part(qemu_coroutine_self());

        offset_in_cluster = offset_into_cluster(s, offset);

        cur_bytes = MIN(bytes, INT_MAX);

        if (bs->encrypted) {

            cur_bytes = MIN(cur_bytes,

                            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                            - offset_in_cluster);

        }



        ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,

                                         &cluster_offset, &l2meta);

        if (ret < 0) {

            goto fail;

        }



        assert((cluster_offset & 511) == 0);



        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);



        if (bs->encrypted) {

            Error *err = NULL;

            assert(s->crypto);

            if (!cluster_data) {

                cluster_data = qemu_try_blockalign(bs->file->bs,

                                                   QCOW_MAX_CRYPT_CLUSTERS

                                                   * s->cluster_size);

                if (cluster_data == NULL) {

                    ret = -ENOMEM;

                    goto fail;

                }

            }



            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

            qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);



            if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,

                                      cluster_data,

                                      cur_bytes, &err) < 0) {

                error_free(err);

                ret = -EIO;

                goto fail;

            }



            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);

        }



        ret = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + offset_in_cluster, cur_bytes);

        if (ret < 0) {

            goto fail;

        }



        /* If we need to do COW, check if it's possible to merge the

         * writing of the guest data together with that of the COW regions.

         * If it's not possible (or not necessary) then write the

         * guest data now. */

        if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) {

            qemu_co_mutex_unlock(&s->lock);

            BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

            trace_qcow2_writev_data(qemu_coroutine_self(),

                                    cluster_offset + offset_in_cluster);

            ret = bdrv_co_pwritev(bs->file,

                                  cluster_offset + offset_in_cluster,

                                  cur_bytes, &hd_qiov, 0);

            qemu_co_mutex_lock(&s->lock);

            if (ret < 0) {

                goto fail;

            }

        }



        while (l2meta != NULL) {

            QCowL2Meta *next;



            ret = qcow2_alloc_cluster_link_l2(bs, l2meta);

            if (ret < 0) {

                goto fail;

            }



            /* Take the request off the list of running requests */

            if (l2meta->nb_clusters != 0) {

                QLIST_REMOVE(l2meta, next_in_flight);

            }



            qemu_co_queue_restart_all(&l2meta->dependent_requests);



            next = l2meta->next;

            g_free(l2meta);

            l2meta = next;

        }



        bytes -= cur_bytes;

        offset += cur_bytes;

        bytes_done += cur_bytes;

        trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_bytes);

    }

    ret = 0;



fail:

    qemu_co_mutex_unlock(&s->lock);



    while (l2meta != NULL) {

        QCowL2Meta *next;



        if (l2meta->nb_clusters != 0) {

            QLIST_REMOVE(l2meta, next_in_flight);

        }

        qemu_co_queue_restart_all(&l2meta->dependent_requests);



        next = l2meta->next;

        g_free(l2meta);

        l2meta = next;

    }



    qemu_iovec_destroy(&hd_qiov);

    qemu_vfree(cluster_data);

    trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);



    return ret;

}

static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,

                                         uint64_t bytes, QEMUIOVector *qiov,

                                         int flags)

{

    BDRVQcow2State *s = bs->opaque;

    int offset_in_cluster;

    int ret;

    unsigned int cur_bytes; 

    uint64_t cluster_offset;

    QEMUIOVector hd_qiov;

    uint64_t bytes_done = 0;

    uint8_t *cluster_data = NULL;

    QCowL2Meta *l2meta = NULL;



    trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);



    qemu_iovec_init(&hd_qiov, qiov->niov);



    s->cluster_cache_offset = -1; 



    qemu_co_mutex_lock(&s->lock);



    while (bytes != 0) {



        l2meta = NULL;



        trace_qcow2_writev_start_part(qemu_coroutine_self());

        offset_in_cluster = offset_into_cluster(s, offset);

        cur_bytes = MIN(bytes, INT_MAX);

        if (bs->encrypted) {

            cur_bytes = MIN(cur_bytes,

                            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                            - offset_in_cluster);

        }



        ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,

                                         &cluster_offset, &l2meta);

        if (ret < 0) {

            goto fail;

        }



        assert((cluster_offset & 511) == 0);



        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes);



        if (bs->encrypted) {

            Error *err = NULL;

            assert(s->crypto);

            if (!cluster_data) {

                cluster_data = qemu_try_blockalign(bs->file->bs,

                                                   QCOW_MAX_CRYPT_CLUSTERS

                                                   * s->cluster_size);

                if (cluster_data == NULL) {

                    ret = -ENOMEM;

                    goto fail;

                }

            }



            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

            qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);



            if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,

                                      cluster_data,

                                      cur_bytes, &err) < 0) {

                error_free(err);

                ret = -EIO;

                goto fail;

            }



            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes);

        }



        ret = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + offset_in_cluster, cur_bytes);

        if (ret < 0) {

            goto fail;

        }



        







        if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) {

            qemu_co_mutex_unlock(&s->lock);

            BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

            trace_qcow2_writev_data(qemu_coroutine_self(),

                                    cluster_offset + offset_in_cluster);

            ret = bdrv_co_pwritev(bs->file,

                                  cluster_offset + offset_in_cluster,

                                  cur_bytes, &hd_qiov, 0);

            qemu_co_mutex_lock(&s->lock);

            if (ret < 0) {

                goto fail;

            }

        }



        while (l2meta != NULL) {

            QCowL2Meta *next;



            ret = qcow2_alloc_cluster_link_l2(bs, l2meta);

            if (ret < 0) {

                goto fail;

            }



            

            if (l2meta->nb_clusters != 0) {

                QLIST_REMOVE(l2meta, next_in_flight);

            }



            qemu_co_queue_restart_all(&l2meta->dependent_requests);



            next = l2meta->next;

            g_free(l2meta);

            l2meta = next;

        }



        bytes -= cur_bytes;

        offset += cur_bytes;

        bytes_done += cur_bytes;

        trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_bytes);

    }

    ret = 0;



fail:

    qemu_co_mutex_unlock(&s->lock);



    while (l2meta != NULL) {

        QCowL2Meta *next;



        if (l2meta->nb_clusters != 0) {

            QLIST_REMOVE(l2meta, next_in_flight);

        }

        qemu_co_queue_restart_all(&l2meta->dependent_requests);



        next = l2meta->next;

        g_free(l2meta);

        l2meta = next;

    }



    qemu_iovec_destroy(&hd_qiov);

    qemu_vfree(cluster_data);

    trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);



    return ret;

}

            if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,
static coroutine_fn int FUNC_0(BlockDriverState *bs, uint64_t offset,

                                         uint64_t bytes, QEMUIOVector *qiov,

                                         int flags)

{

    BDRVQcow2State *s = bs->opaque;

    int VAR_0;

    int VAR_1;

    unsigned int VAR_2; 

    uint64_t cluster_offset;

    QEMUIOVector hd_qiov;

    uint64_t bytes_done = 0;

    uint8_t *cluster_data = NULL;

    QCowL2Meta *l2meta = NULL;



    trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);



    qemu_iovec_init(&hd_qiov, qiov->niov);



    s->cluster_cache_offset = -1; 



    qemu_co_mutex_lock(&s->lock);



    while (bytes != 0) {



        l2meta = NULL;



        trace_qcow2_writev_start_part(qemu_coroutine_self());

        VAR_0 = offset_into_cluster(s, offset);

        VAR_2 = MIN(bytes, INT_MAX);

        if (bs->encrypted) {

            VAR_2 = MIN(VAR_2,

                            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                            - VAR_0);

        }



        VAR_1 = qcow2_alloc_cluster_offset(bs, offset, &VAR_2,

                                         &cluster_offset, &l2meta);

        if (VAR_1 < 0) {

            goto fail;

        }



        assert((cluster_offset & 511) == 0);



        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, VAR_2);



        if (bs->encrypted) {

            Error *err = NULL;

            assert(s->crypto);

            if (!cluster_data) {

                cluster_data = qemu_try_blockalign(bs->file->bs,

                                                   QCOW_MAX_CRYPT_CLUSTERS

                                                   * s->cluster_size);

                if (cluster_data == NULL) {

                    VAR_1 = -ENOMEM;

                    goto fail;

                }

            }



            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

            qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);



            if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,

                                      cluster_data,

                                      VAR_2, &err) < 0) {

                error_free(err);

                VAR_1 = -EIO;

                goto fail;

            }



            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data, VAR_2);

        }



        VAR_1 = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + VAR_0, VAR_2);

        if (VAR_1 < 0) {

            goto fail;

        }



        







        if (!merge_cow(offset, VAR_2, &hd_qiov, l2meta)) {

            qemu_co_mutex_unlock(&s->lock);

            BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

            trace_qcow2_writev_data(qemu_coroutine_self(),

                                    cluster_offset + VAR_0);

            VAR_1 = bdrv_co_pwritev(bs->file,

                                  cluster_offset + VAR_0,

                                  VAR_2, &hd_qiov, 0);

            qemu_co_mutex_lock(&s->lock);

            if (VAR_1 < 0) {

                goto fail;

            }

        }



        while (l2meta != NULL) {

            QCowL2Meta *next;



            VAR_1 = qcow2_alloc_cluster_link_l2(bs, l2meta);

            if (VAR_1 < 0) {

                goto fail;

            }



            

            if (l2meta->nb_clusters != 0) {

                QLIST_REMOVE(l2meta, next_in_flight);

            }



            qemu_co_queue_restart_all(&l2meta->dependent_requests);



            next = l2meta->next;

            g_free(l2meta);

            l2meta = next;

        }



        bytes -= VAR_2;

        offset += VAR_2;

        bytes_done += VAR_2;

        trace_qcow2_writev_done_part(qemu_coroutine_self(), VAR_2);

    }

    VAR_1 = 0;



fail:

    qemu_co_mutex_unlock(&s->lock);



    while (l2meta != NULL) {

        QCowL2Meta *next;



        if (l2meta->nb_clusters != 0) {

            QLIST_REMOVE(l2meta, next_in_flight);

        }

        qemu_co_queue_restart_all(&l2meta->dependent_requests);



        next = l2meta->next;

        g_free(l2meta);

        l2meta = next;

    }



    qemu_iovec_destroy(&hd_qiov);

    qemu_vfree(cluster_data);

    trace_qcow2_writev_done_req(qemu_coroutine_self(), VAR_1);



    return VAR_1;

}

static coroutine_fn int FUNC_0(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov,
int flags)
{ BDRVQcow2State *s = bs->opaque; int VAR_0; int VAR_1; unsigned int VAR_2; uint64_t cluster_offset; QEMUIOVector hd_qiov; uint64_t bytes_done = 0; uint8_t *cluster_data = NULL; QCowL2Meta *l2meta = NULL; trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes); qemu_iovec_init(&hd_qiov, qiov->niov); s->cluster_cache_offset = -1; qemu_co_mutex_lock(&s->lock); while (bytes != 0) { l2meta = NULL; trace_qcow2_writev_start_part(qemu_coroutine_self()); VAR_0 = offset_into_cluster(s, offset); VAR_2 = MIN(bytes, INT_MAX); if (bs->encrypted) { VAR_2 = MIN(VAR_2,
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
- VAR_0); } VAR_1 = qcow2_alloc_cluster_offset(bs, offset, &VAR_2,
&cluster_offset, &l2meta); if (VAR_1 < 0) { goto fail; } assert((cluster_offset & 511) == 0); qemu_iovec_reset(&hd_qiov); qemu_iovec_concat(&hd_qiov, qiov, bytes_done, VAR_2); if (bs->encrypted) { Error *err = NULL; assert(s->crypto); if (!cluster_data) { cluster_data = qemu_try_blockalign(bs->file->bs,
QCOW_MAX_CRYPT_CLUSTERS
* s->cluster_size); if (cluster_data == NULL) { VAR_1 = -ENOMEM; goto fail; } } assert(hd_qiov.size <=
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size); if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,
cluster_data,
VAR_2, &err) < 0) { error_free(err); VAR_1 = -EIO; goto fail; } qemu_iovec_reset(&hd_qiov); qemu_iovec_add(&hd_qiov, cluster_data, VAR_2); } VAR_1 = qcow2_pre_write_overlap_check(bs, 0,
cluster_offset + VAR_0, VAR_2); if (VAR_1 < 0) { goto fail; } if (!merge_cow(offset, VAR_2, &hd_qiov, l2meta)) { qemu_co_mutex_unlock(&s->lock); BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); trace_qcow2_writev_data(qemu_coroutine_self(),
cluster_offset + VAR_0); VAR_1 = bdrv_co_pwritev(bs->file,
cluster_offset + VAR_0,
VAR_2, &hd_qiov, 0); qemu_co_mutex_lock(&s->lock); if (VAR_1 < 0) { goto fail; } } while (l2meta != NULL) { QCowL2Meta *next; VAR_1 = qcow2_alloc_cluster_link_l2(bs, l2meta); if (VAR_1 < 0) { goto fail; } if (l2meta->nb_clusters != 0) { QLIST_REMOVE(l2meta, next_in_flight); } qemu_co_queue_restart_all(&l2meta->dependent_requests); next = l2meta->next; g_free(l2meta); l2meta = next; } bytes -= VAR_2; offset += VAR_2; bytes_done += VAR_2; trace_qcow2_writev_done_part(qemu_coroutine_self(), VAR_2); } VAR_1 = 0; fail:
qemu_co_mutex_unlock(&s->lock); while (l2meta != NULL) { QCowL2Meta *next; if (l2meta->nb_clusters != 0) { QLIST_REMOVE(l2meta, next_in_flight); } qemu_co_queue_restart_all(&l2meta->dependent_requests); next = l2meta->next; g_free(l2meta); l2meta = next; } qemu_iovec_destroy(&hd_qiov); qemu_vfree(cluster_data); trace_qcow2_writev_done_req(qemu_coroutine_self(), VAR_1); return VAR_1; }