static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,

                          int remaining_sectors, QEMUIOVector *qiov)

{

    BDRVQcowState *s = bs->opaque;

    int index_in_cluster, n1;

    int ret;

    int cur_nr_sectors; /* number of sectors in current iteration */

    uint64_t cluster_offset = 0;

    uint64_t bytes_done = 0;

    QEMUIOVector hd_qiov;

    uint8_t *cluster_data = NULL;



    qemu_iovec_init(&hd_qiov, qiov->niov);



    qemu_co_mutex_lock(&s->lock);



    while (remaining_sectors != 0) {



        /* prepare next request */

        cur_nr_sectors = remaining_sectors;

        if (s->crypt_method) {

            cur_nr_sectors = MIN(cur_nr_sectors,

                QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);

        }



        ret = qcow2_get_cluster_offset(bs, sector_num << 9,

            &cur_nr_sectors, &cluster_offset);

        if (ret < 0) {

            goto fail;

        }



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



        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_copy(&hd_qiov, qiov, bytes_done,

            cur_nr_sectors * 512);



        if (!cluster_offset) {



            if (bs->backing_hd) {

                /* read from the base image */

                n1 = qcow2_backing_read1(bs->backing_hd, &hd_qiov,

                    sector_num, cur_nr_sectors);

                if (n1 > 0) {

                    BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);

                    qemu_co_mutex_unlock(&s->lock);

                    ret = bdrv_co_readv(bs->backing_hd, sector_num,

                                        n1, &hd_qiov);

                    qemu_co_mutex_lock(&s->lock);

                    if (ret < 0) {

                        goto fail;

                    }

                }

            } else {

                /* Note: in this case, no need to wait */

                qemu_iovec_memset(&hd_qiov, 0, 512 * cur_nr_sectors);

            }

        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {

            /* add AIO support for compressed blocks ? */

            ret = qcow2_decompress_cluster(bs, cluster_offset);

            if (ret < 0) {

                goto fail;

            }



            qemu_iovec_from_buffer(&hd_qiov,

                s->cluster_cache + index_in_cluster * 512,

                512 * cur_nr_sectors);

        } else {

            if ((cluster_offset & 511) != 0) {

                ret = -EIO;

                goto fail;

            }



            if (s->crypt_method) {

                /*

                 * For encrypted images, read everything into a temporary

                 * contiguous buffer on which the AES functions can work.

                 */

                if (!cluster_data) {

                    cluster_data =

                        g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

                }



                assert(cur_nr_sectors <=

                    QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);

                qemu_iovec_reset(&hd_qiov);

                qemu_iovec_add(&hd_qiov, cluster_data,

                    512 * cur_nr_sectors);

            }



            BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);

            qemu_co_mutex_unlock(&s->lock);

            ret = bdrv_co_readv(bs->file,

                                (cluster_offset >> 9) + index_in_cluster,

                                cur_nr_sectors, &hd_qiov);

            qemu_co_mutex_lock(&s->lock);

            if (ret < 0) {

                goto fail;

            }

            if (s->crypt_method) {

                qcow2_encrypt_sectors(s, sector_num,  cluster_data,

                    cluster_data, cur_nr_sectors, 0, &s->aes_decrypt_key);

                qemu_iovec_reset(&hd_qiov);

                qemu_iovec_copy(&hd_qiov, qiov, bytes_done,

                    cur_nr_sectors * 512);

                qemu_iovec_from_buffer(&hd_qiov, cluster_data,

                    512 * cur_nr_sectors);

            }

        }



        remaining_sectors -= cur_nr_sectors;

        sector_num += cur_nr_sectors;

        bytes_done += cur_nr_sectors * 512;

    }

    ret = 0;



fail:

    qemu_co_mutex_unlock(&s->lock);



    qemu_iovec_destroy(&hd_qiov);




    return ret;

}
static int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,

                          int remaining_sectors, QEMUIOVector *qiov)

{

    BDRVQcowState *s = bs->opaque;

    int index_in_cluster, n1;

    int ret;

    int cur_nr_sectors; 

    uint64_t cluster_offset = 0;

    uint64_t bytes_done = 0;

    QEMUIOVector hd_qiov;

    uint8_t *cluster_data = NULL;



    qemu_iovec_init(&hd_qiov, qiov->niov);



    qemu_co_mutex_lock(&s->lock);



    while (remaining_sectors != 0) {



        

        cur_nr_sectors = remaining_sectors;

        if (s->crypt_method) {

            cur_nr_sectors = MIN(cur_nr_sectors,

                QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);

        }



        ret = qcow2_get_cluster_offset(bs, sector_num << 9,

            &cur_nr_sectors, &cluster_offset);

        if (ret < 0) {

            goto fail;

        }



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



        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_copy(&hd_qiov, qiov, bytes_done,

            cur_nr_sectors * 512);



        if (!cluster_offset) {



            if (bs->backing_hd) {

                

                n1 = qcow2_backing_read1(bs->backing_hd, &hd_qiov,

                    sector_num, cur_nr_sectors);

                if (n1 > 0) {

                    BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);

                    qemu_co_mutex_unlock(&s->lock);

                    ret = bdrv_co_readv(bs->backing_hd, sector_num,

                                        n1, &hd_qiov);

                    qemu_co_mutex_lock(&s->lock);

                    if (ret < 0) {

                        goto fail;

                    }

                }

            } else {

                

                qemu_iovec_memset(&hd_qiov, 0, 512 * cur_nr_sectors);

            }

        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {

            

            ret = qcow2_decompress_cluster(bs, cluster_offset);

            if (ret < 0) {

                goto fail;

            }



            qemu_iovec_from_buffer(&hd_qiov,

                s->cluster_cache + index_in_cluster * 512,

                512 * cur_nr_sectors);

        } else {

            if ((cluster_offset & 511) != 0) {

                ret = -EIO;

                goto fail;

            }



            if (s->crypt_method) {

                







                if (!cluster_data) {

                    cluster_data =

                        g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

                }



                assert(cur_nr_sectors <=

                    QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);

                qemu_iovec_reset(&hd_qiov);

                qemu_iovec_add(&hd_qiov, cluster_data,

                    512 * cur_nr_sectors);

            }



            BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);

            qemu_co_mutex_unlock(&s->lock);

            ret = bdrv_co_readv(bs->file,

                                (cluster_offset >> 9) + index_in_cluster,

                                cur_nr_sectors, &hd_qiov);

            qemu_co_mutex_lock(&s->lock);

            if (ret < 0) {

                goto fail;

            }

            if (s->crypt_method) {

                qcow2_encrypt_sectors(s, sector_num,  cluster_data,

                    cluster_data, cur_nr_sectors, 0, &s->aes_decrypt_key);

                qemu_iovec_reset(&hd_qiov);

                qemu_iovec_copy(&hd_qiov, qiov, bytes_done,

                    cur_nr_sectors * 512);

                qemu_iovec_from_buffer(&hd_qiov, cluster_data,

                    512 * cur_nr_sectors);

            }

        }



        remaining_sectors -= cur_nr_sectors;

        sector_num += cur_nr_sectors;

        bytes_done += cur_nr_sectors * 512;

    }

    ret = 0;



fail:

    qemu_co_mutex_unlock(&s->lock);



    qemu_iovec_destroy(&hd_qiov);




    return ret;

}
static int FUNC_0(BlockDriverState *VAR_0, int64_t VAR_1,

                          int VAR_2, QEMUIOVector *VAR_3)

{

    BDRVQcowState *s = VAR_0->opaque;

    int VAR_4, VAR_5;

    int VAR_6;

    int VAR_7; 

    uint64_t cluster_offset = 0;

    uint64_t bytes_done = 0;

    QEMUIOVector hd_qiov;

    uint8_t *cluster_data = NULL;



    qemu_iovec_init(&hd_qiov, VAR_3->niov);



    qemu_co_mutex_lock(&s->lock);



    while (VAR_2 != 0) {



        

        VAR_7 = VAR_2;

        if (s->crypt_method) {

            VAR_7 = MIN(VAR_7,

                QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);

        }



        VAR_6 = qcow2_get_cluster_offset(VAR_0, VAR_1 << 9,

            &VAR_7, &cluster_offset);

        if (VAR_6 < 0) {

            goto fail;

        }



        VAR_4 = VAR_1 & (s->cluster_sectors - 1);



        qemu_iovec_reset(&hd_qiov);

        qemu_iovec_copy(&hd_qiov, VAR_3, bytes_done,

            VAR_7 * 512);



        if (!cluster_offset) {



            if (VAR_0->backing_hd) {

                

                VAR_5 = qcow2_backing_read1(VAR_0->backing_hd, &hd_qiov,

                    VAR_1, VAR_7);

                if (VAR_5 > 0) {

                    BLKDBG_EVENT(VAR_0->file, BLKDBG_READ_BACKING_AIO);

                    qemu_co_mutex_unlock(&s->lock);

                    VAR_6 = bdrv_co_readv(VAR_0->backing_hd, VAR_1,

                                        VAR_5, &hd_qiov);

                    qemu_co_mutex_lock(&s->lock);

                    if (VAR_6 < 0) {

                        goto fail;

                    }

                }

            } else {

                

                qemu_iovec_memset(&hd_qiov, 0, 512 * VAR_7);

            }

        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {

            

            VAR_6 = qcow2_decompress_cluster(VAR_0, cluster_offset);

            if (VAR_6 < 0) {

                goto fail;

            }



            qemu_iovec_from_buffer(&hd_qiov,

                s->cluster_cache + VAR_4 * 512,

                512 * VAR_7);

        } else {

            if ((cluster_offset & 511) != 0) {

                VAR_6 = -EIO;

                goto fail;

            }



            if (s->crypt_method) {

                







                if (!cluster_data) {

                    cluster_data =

                        g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);

                }



                assert(VAR_7 <=

                    QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);

                qemu_iovec_reset(&hd_qiov);

                qemu_iovec_add(&hd_qiov, cluster_data,

                    512 * VAR_7);

            }



            BLKDBG_EVENT(VAR_0->file, BLKDBG_READ_AIO);

            qemu_co_mutex_unlock(&s->lock);

            VAR_6 = bdrv_co_readv(VAR_0->file,

                                (cluster_offset >> 9) + VAR_4,

                                VAR_7, &hd_qiov);

            qemu_co_mutex_lock(&s->lock);

            if (VAR_6 < 0) {

                goto fail;

            }

            if (s->crypt_method) {

                qcow2_encrypt_sectors(s, VAR_1,  cluster_data,

                    cluster_data, VAR_7, 0, &s->aes_decrypt_key);

                qemu_iovec_reset(&hd_qiov);

                qemu_iovec_copy(&hd_qiov, VAR_3, bytes_done,

                    VAR_7 * 512);

                qemu_iovec_from_buffer(&hd_qiov, cluster_data,

                    512 * VAR_7);

            }

        }



        VAR_2 -= VAR_7;

        VAR_1 += VAR_7;

        bytes_done += VAR_7 * 512;

    }

    VAR_6 = 0;



fail:

    qemu_co_mutex_unlock(&s->lock);



    qemu_iovec_destroy(&hd_qiov);




    return VAR_6;

}
static int FUNC_0(BlockDriverState *VAR_0, int64_t VAR_1,
int VAR_2, QEMUIOVector *VAR_3)
{ BDRVQcowState *s = VAR_0->opaque; int VAR_4, VAR_5; int VAR_6; int VAR_7; uint64_t cluster_offset = 0; uint64_t bytes_done = 0; QEMUIOVector hd_qiov; uint8_t *cluster_data = NULL; qemu_iovec_init(&hd_qiov, VAR_3->niov); qemu_co_mutex_lock(&s->lock); while (VAR_2 != 0) { VAR_7 = VAR_2; if (s->crypt_method) { VAR_7 = MIN(VAR_7,
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); } VAR_6 = qcow2_get_cluster_offset(VAR_0, VAR_1 << 9,
&VAR_7, &cluster_offset); if (VAR_6 < 0) { goto fail; } VAR_4 = VAR_1 & (s->cluster_sectors - 1); qemu_iovec_reset(&hd_qiov); qemu_iovec_copy(&hd_qiov, VAR_3, bytes_done,
VAR_7 * 512); if (!cluster_offset) { if (VAR_0->backing_hd) { VAR_5 = qcow2_backing_read1(VAR_0->backing_hd, &hd_qiov,
VAR_1, VAR_7); if (VAR_5 > 0) { BLKDBG_EVENT(VAR_0->file, BLKDBG_READ_BACKING_AIO); qemu_co_mutex_unlock(&s->lock); VAR_6 = bdrv_co_readv(VAR_0->backing_hd, VAR_1,
VAR_5, &hd_qiov); qemu_co_mutex_lock(&s->lock); if (VAR_6 < 0) { goto fail; } } } else { qemu_iovec_memset(&hd_qiov, 0, 512 * VAR_7); } } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { VAR_6 = qcow2_decompress_cluster(VAR_0, cluster_offset); if (VAR_6 < 0) { goto fail; } qemu_iovec_from_buffer(&hd_qiov,
s->cluster_cache + VAR_4 * 512,
512 * VAR_7); } else { if ((cluster_offset & 511) != 0) { VAR_6 = -EIO; goto fail; } if (s->crypt_method) { if (!cluster_data) { cluster_data =
g_malloc0(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); } assert(VAR_7 <=
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors); qemu_iovec_reset(&hd_qiov); qemu_iovec_add(&hd_qiov, cluster_data,
512 * VAR_7); } BLKDBG_EVENT(VAR_0->file, BLKDBG_READ_AIO); qemu_co_mutex_unlock(&s->lock); VAR_6 = bdrv_co_readv(VAR_0->file,
(cluster_offset >> 9) + VAR_4,
VAR_7, &hd_qiov); qemu_co_mutex_lock(&s->lock); if (VAR_6 < 0) { goto fail; } if (s->crypt_method) { qcow2_encrypt_sectors(s, VAR_1,  cluster_data,
cluster_data, VAR_7, 0, &s->aes_decrypt_key); qemu_iovec_reset(&hd_qiov); qemu_iovec_copy(&hd_qiov, VAR_3, bytes_done,
VAR_7 * 512); qemu_iovec_from_buffer(&hd_qiov, cluster_data,
512 * VAR_7); } } VAR_2 -= VAR_7; VAR_1 += VAR_7; bytes_done += VAR_7 * 512; } VAR_6 = 0; fail:
qemu_co_mutex_unlock(&s->lock); qemu_iovec_destroy(&hd_qiov); return VAR_6; }