static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,

                           int64_t sector_num,

                           int remaining_sectors,

                           QEMUIOVector *qiov)

{

    BDRVQcowState *s = bs->opaque;

    int index_in_cluster;

    int ret;

    int cur_nr_sectors; /* 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(), sector_num,

                                 remaining_sectors);



    qemu_iovec_init(&hd_qiov, qiov->niov);



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



    qemu_co_mutex_lock(&s->lock);



    while (remaining_sectors != 0) {



        l2meta = NULL;



        trace_qcow2_writev_start_part(qemu_coroutine_self());

        index_in_cluster = sector_num & (s->cluster_sectors - 1);

        cur_nr_sectors = remaining_sectors;

        if (s->crypt_method &&

            cur_nr_sectors >

            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster) {

            cur_nr_sectors =

                QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster;

        }



        ret = qcow2_alloc_cluster_offset(bs, sector_num << 9,

            &cur_nr_sectors, &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_nr_sectors * 512);



        if (s->crypt_method) {

            if (!cluster_data) {

                cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS *

                                                 s->cluster_size);

            }



            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

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



            qcow2_encrypt_sectors(s, sector_num, cluster_data,

                cluster_data, cur_nr_sectors, 1, &s->aes_encrypt_key);



            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data,

                cur_nr_sectors * 512);

        }



        ret = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE,

                cur_nr_sectors * BDRV_SECTOR_SIZE);

        if (ret < 0) {

            goto fail;

        }



        qemu_co_mutex_unlock(&s->lock);

        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

        trace_qcow2_writev_data(qemu_coroutine_self(),

                                (cluster_offset >> 9) + index_in_cluster);

        ret = bdrv_co_writev(bs->file,

                             (cluster_offset >> 9) + index_in_cluster,

                             cur_nr_sectors, &hd_qiov);

        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;

        }



        remaining_sectors -= cur_nr_sectors;

        sector_num += cur_nr_sectors;

        bytes_done += cur_nr_sectors * 512;

        trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_nr_sectors);

    }

    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_writev(BlockDriverState *bs,

                           int64_t sector_num,

                           int remaining_sectors,

                           QEMUIOVector *qiov)

{

    BDRVQcowState *s = bs->opaque;

    int index_in_cluster;

    int ret;

    int cur_nr_sectors; 

    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(), sector_num,

                                 remaining_sectors);



    qemu_iovec_init(&hd_qiov, qiov->niov);



    s->cluster_cache_offset = -1; 



    qemu_co_mutex_lock(&s->lock);



    while (remaining_sectors != 0) {



        l2meta = NULL;



        trace_qcow2_writev_start_part(qemu_coroutine_self());

        index_in_cluster = sector_num & (s->cluster_sectors - 1);

        cur_nr_sectors = remaining_sectors;

        if (s->crypt_method &&

            cur_nr_sectors >

            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster) {

            cur_nr_sectors =

                QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster;

        }



        ret = qcow2_alloc_cluster_offset(bs, sector_num << 9,

            &cur_nr_sectors, &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_nr_sectors * 512);



        if (s->crypt_method) {

            if (!cluster_data) {

                cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS *

                                                 s->cluster_size);

            }



            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

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



            qcow2_encrypt_sectors(s, sector_num, cluster_data,

                cluster_data, cur_nr_sectors, 1, &s->aes_encrypt_key);



            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data,

                cur_nr_sectors * 512);

        }



        ret = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE,

                cur_nr_sectors * BDRV_SECTOR_SIZE);

        if (ret < 0) {

            goto fail;

        }



        qemu_co_mutex_unlock(&s->lock);

        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

        trace_qcow2_writev_data(qemu_coroutine_self(),

                                (cluster_offset >> 9) + index_in_cluster);

        ret = bdrv_co_writev(bs->file,

                             (cluster_offset >> 9) + index_in_cluster,

                             cur_nr_sectors, &hd_qiov);

        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;

        }



        remaining_sectors -= cur_nr_sectors;

        sector_num += cur_nr_sectors;

        bytes_done += cur_nr_sectors * 512;

        trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_nr_sectors);

    }

    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;

}

                cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS *                                                  s->cluster_size);
static coroutine_fn int FUNC_0(BlockDriverState *bs,

                           int64_t sector_num,

                           int remaining_sectors,

                           QEMUIOVector *qiov)

{

    BDRVQcowState *s = bs->opaque;

    int VAR_0;

    int VAR_1;

    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(), sector_num,

                                 remaining_sectors);



    qemu_iovec_init(&hd_qiov, qiov->niov);



    s->cluster_cache_offset = -1; 



    qemu_co_mutex_lock(&s->lock);



    while (remaining_sectors != 0) {



        l2meta = NULL;



        trace_qcow2_writev_start_part(qemu_coroutine_self());

        VAR_0 = sector_num & (s->cluster_sectors - 1);

        VAR_2 = remaining_sectors;

        if (s->crypt_method &&

            VAR_2 >

            QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - VAR_0) {

            VAR_2 =

                QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - VAR_0;

        }



        VAR_1 = qcow2_alloc_cluster_offset(bs, sector_num << 9,

            &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 * 512);



        if (s->crypt_method) {

            if (!cluster_data) {

                cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS *

                                                 s->cluster_size);

            }



            assert(hd_qiov.size <=

                   QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

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



            qcow2_encrypt_sectors(s, sector_num, cluster_data,

                cluster_data, VAR_2, 1, &s->aes_encrypt_key);



            qemu_iovec_reset(&hd_qiov);

            qemu_iovec_add(&hd_qiov, cluster_data,

                VAR_2 * 512);

        }



        VAR_1 = qcow2_pre_write_overlap_check(bs, 0,

                cluster_offset + VAR_0 * BDRV_SECTOR_SIZE,

                VAR_2 * BDRV_SECTOR_SIZE);

        if (VAR_1 < 0) {

            goto fail;

        }



        qemu_co_mutex_unlock(&s->lock);

        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);

        trace_qcow2_writev_data(qemu_coroutine_self(),

                                (cluster_offset >> 9) + VAR_0);

        VAR_1 = bdrv_co_writev(bs->file,

                             (cluster_offset >> 9) + VAR_0,

                             VAR_2, &hd_qiov);

        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;

        }



        remaining_sectors -= VAR_2;

        sector_num += VAR_2;

        bytes_done += VAR_2 * 512;

        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,
int64_t sector_num,
int remaining_sectors,
QEMUIOVector *qiov)
{ BDRVQcowState *s = bs->opaque; int VAR_0; int VAR_1; 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(), sector_num,
remaining_sectors); qemu_iovec_init(&hd_qiov, qiov->niov); s->cluster_cache_offset = -1; qemu_co_mutex_lock(&s->lock); while (remaining_sectors != 0) { l2meta = NULL; trace_qcow2_writev_start_part(qemu_coroutine_self()); VAR_0 = sector_num & (s->cluster_sectors - 1); VAR_2 = remaining_sectors; if (s->crypt_method &&
VAR_2 >
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - VAR_0) { VAR_2 =
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - VAR_0; } VAR_1 = qcow2_alloc_cluster_offset(bs, sector_num << 9,
&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 * 512); if (s->crypt_method) { if (!cluster_data) { cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS *
s->cluster_size); } assert(hd_qiov.size <=
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size); qcow2_encrypt_sectors(s, sector_num, cluster_data,
cluster_data, VAR_2, 1, &s->aes_encrypt_key); qemu_iovec_reset(&hd_qiov); qemu_iovec_add(&hd_qiov, cluster_data,
VAR_2 * 512); } VAR_1 = qcow2_pre_write_overlap_check(bs, 0,
cluster_offset + VAR_0 * BDRV_SECTOR_SIZE,
VAR_2 * BDRV_SECTOR_SIZE); if (VAR_1 < 0) { goto fail; } qemu_co_mutex_unlock(&s->lock); BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); trace_qcow2_writev_data(qemu_coroutine_self(),
(cluster_offset >> 9) + VAR_0); VAR_1 = bdrv_co_writev(bs->file,
(cluster_offset >> 9) + VAR_0,
VAR_2, &hd_qiov); 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; } remaining_sectors -= VAR_2; sector_num += VAR_2; bytes_done += VAR_2 * 512; 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; }