static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,

    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)

{

    BDRVQcowState *s = bs->opaque;

    int l2_index;

    uint64_t *l2_table;

    uint64_t entry;

    unsigned int nb_clusters;

    int ret;



    uint64_t alloc_cluster_offset;



    trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,

                             *bytes);

    assert(*bytes > 0);



    /*

     * Calculate the number of clusters to look for. We stop at L2 table

     * boundaries to keep things simple.

     */

    nb_clusters =

        size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);



    l2_index = offset_to_l2_index(s, guest_offset);

    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);



    /* Find L2 entry for the first involved cluster */

    ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);

    if (ret < 0) {

        return ret;

    }



    entry = be64_to_cpu(l2_table[l2_index]);



    /* For the moment, overwrite compressed clusters one by one */

    if (entry & QCOW_OFLAG_COMPRESSED) {

        nb_clusters = 1;

    } else {

        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);

    }



    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);

    if (ret < 0) {

        return ret;

    }



    if (nb_clusters == 0) {

        *bytes = 0;

        return 0;

    }



    /* Allocate, if necessary at a given offset in the image file */

    alloc_cluster_offset = start_of_cluster(s, *host_offset);

    ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,

                                  &nb_clusters);

    if (ret < 0) {

        goto fail;

    }



    /* Can't extend contiguous allocation */

    if (nb_clusters == 0) {

        *bytes = 0;

        return 0;

    }



    /*

     * Save info needed for meta data update.

     *

     * requested_sectors: Number of sectors from the start of the first

     * newly allocated cluster to the end of the (possibly shortened

     * before) write request.

     *

     * avail_sectors: Number of sectors from the start of the first

     * newly allocated to the end of the last newly allocated cluster.

     *

     * nb_sectors: The number of sectors from the start of the first

     * newly allocated cluster to the end of the area that the write

     * request actually writes to (excluding COW at the end)

     */

    int requested_sectors =

        (*bytes + offset_into_cluster(s, guest_offset))

        >> BDRV_SECTOR_BITS;

    int avail_sectors = nb_clusters

                        << (s->cluster_bits - BDRV_SECTOR_BITS);

    int alloc_n_start = offset_into_cluster(s, guest_offset)

                        >> BDRV_SECTOR_BITS;

    int nb_sectors = MIN(requested_sectors, avail_sectors);

    QCowL2Meta *old_m = *m;



    *m = g_malloc0(sizeof(**m));



    **m = (QCowL2Meta) {

        .next           = old_m,



        .alloc_offset   = alloc_cluster_offset,

        .offset         = start_of_cluster(s, guest_offset),

        .nb_clusters    = nb_clusters,

        .nb_available   = nb_sectors,



        .cow_start = {

            .offset     = 0,

            .nb_sectors = alloc_n_start,

        },

        .cow_end = {

            .offset     = nb_sectors * BDRV_SECTOR_SIZE,

            .nb_sectors = avail_sectors - nb_sectors,

        },

    };

    qemu_co_queue_init(&(*m)->dependent_requests);

    QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);



    *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);

    *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)

                         - offset_into_cluster(s, guest_offset));

    assert(*bytes != 0);



    return 1;



fail:

    if (*m && (*m)->nb_clusters > 0) {

        QLIST_REMOVE(*m, next_in_flight);

    }

    return ret;

}

static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,

    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)

{

    BDRVQcowState *s = bs->opaque;

    int l2_index;

    uint64_t *l2_table;

    uint64_t entry;

    unsigned int nb_clusters;

    int ret;



    uint64_t alloc_cluster_offset;



    trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,

                             *bytes);

    assert(*bytes > 0);



    







    nb_clusters =

        size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);



    l2_index = offset_to_l2_index(s, guest_offset);

    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);



    

    ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);

    if (ret < 0) {

        return ret;

    }



    entry = be64_to_cpu(l2_table[l2_index]);



    

    if (entry & QCOW_OFLAG_COMPRESSED) {

        nb_clusters = 1;

    } else {

        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);

    }



    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);

    if (ret < 0) {

        return ret;

    }



    if (nb_clusters == 0) {

        *bytes = 0;

        return 0;

    }



    

    alloc_cluster_offset = start_of_cluster(s, *host_offset);

    ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,

                                  &nb_clusters);

    if (ret < 0) {

        goto fail;

    }



    

    if (nb_clusters == 0) {

        *bytes = 0;

        return 0;

    }



    



























    int requested_sectors =

        (*bytes + offset_into_cluster(s, guest_offset))

        >> BDRV_SECTOR_BITS;

    int avail_sectors = nb_clusters

                        << (s->cluster_bits - BDRV_SECTOR_BITS);

    int alloc_n_start = offset_into_cluster(s, guest_offset)

                        >> BDRV_SECTOR_BITS;

    int nb_sectors = MIN(requested_sectors, avail_sectors);

    QCowL2Meta *old_m = *m;



    *m = g_malloc0(sizeof(**m));



    **m = (QCowL2Meta) {

        .next           = old_m,



        .alloc_offset   = alloc_cluster_offset,

        .offset         = start_of_cluster(s, guest_offset),

        .nb_clusters    = nb_clusters,

        .nb_available   = nb_sectors,



        .cow_start = {

            .offset     = 0,

            .nb_sectors = alloc_n_start,

        },

        .cow_end = {

            .offset     = nb_sectors * BDRV_SECTOR_SIZE,

            .nb_sectors = avail_sectors - nb_sectors,

        },

    };

    qemu_co_queue_init(&(*m)->dependent_requests);

    QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);



    *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);

    *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)

                         - offset_into_cluster(s, guest_offset));

    assert(*bytes != 0);



    return 1;



fail:

    if (*m && (*m)->nb_clusters > 0) {

        QLIST_REMOVE(*m, next_in_flight);

    }

    return ret;

}

    if (nb_clusters == 0) {         *bytes = 0;         return 0;
static int FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,

    uint64_t *VAR_2, uint64_t *VAR_3, QCowL2Meta **VAR_4)

{

    BDRVQcowState *s = VAR_0->opaque;

    int VAR_5;

    uint64_t *l2_table;

    uint64_t entry;

    unsigned int VAR_6;

    int VAR_7;



    uint64_t alloc_cluster_offset;



    trace_qcow2_handle_alloc(qemu_coroutine_self(), VAR_1, *VAR_2,

                             *VAR_3);

    assert(*VAR_3 > 0);



    







    VAR_6 =

        size_to_clusters(s, offset_into_cluster(s, VAR_1) + *VAR_3);



    VAR_5 = offset_to_l2_index(s, VAR_1);

    VAR_6 = MIN(VAR_6, s->l2_size - VAR_5);



    

    VAR_7 = get_cluster_table(VAR_0, VAR_1, &l2_table, &VAR_5);

    if (VAR_7 < 0) {

        return VAR_7;

    }



    entry = be64_to_cpu(l2_table[VAR_5]);



    

    if (entry & QCOW_OFLAG_COMPRESSED) {

        VAR_6 = 1;

    } else {

        VAR_6 = count_cow_clusters(s, VAR_6, l2_table, VAR_5);

    }



    VAR_7 = qcow2_cache_put(VAR_0, s->l2_table_cache, (void**) &l2_table);

    if (VAR_7 < 0) {

        return VAR_7;

    }



    if (VAR_6 == 0) {

        *VAR_3 = 0;

        return 0;

    }



    

    alloc_cluster_offset = start_of_cluster(s, *VAR_2);

    VAR_7 = do_alloc_cluster_offset(VAR_0, VAR_1, &alloc_cluster_offset,

                                  &VAR_6);

    if (VAR_7 < 0) {

        goto fail;

    }



    

    if (VAR_6 == 0) {

        *VAR_3 = 0;

        return 0;

    }



    



























    int VAR_8 =

        (*VAR_3 + offset_into_cluster(s, VAR_1))

        >> BDRV_SECTOR_BITS;

    int VAR_9 = VAR_6

                        << (s->cluster_bits - BDRV_SECTOR_BITS);

    int VAR_10 = offset_into_cluster(s, VAR_1)

                        >> BDRV_SECTOR_BITS;

    int VAR_11 = MIN(VAR_8, VAR_9);

    QCowL2Meta *old_m = *VAR_4;



    *VAR_4 = g_malloc0(sizeof(**VAR_4));



    **VAR_4 = (QCowL2Meta) {

        .next           = old_m,



        .alloc_offset   = alloc_cluster_offset,

        .offset         = start_of_cluster(s, VAR_1),

        .VAR_6    = VAR_6,

        .nb_available   = VAR_11,



        .cow_start = {

            .offset     = 0,

            .VAR_11 = VAR_10,

        },

        .cow_end = {

            .offset     = VAR_11 * BDRV_SECTOR_SIZE,

            .VAR_11 = VAR_9 - VAR_11,

        },

    };

    qemu_co_queue_init(&(*VAR_4)->dependent_requests);

    QLIST_INSERT_HEAD(&s->cluster_allocs, *VAR_4, next_in_flight);



    *VAR_2 = alloc_cluster_offset + offset_into_cluster(s, VAR_1);

    *VAR_3 = MIN(*VAR_3, (VAR_11 * BDRV_SECTOR_SIZE)

                         - offset_into_cluster(s, VAR_1));

    assert(*VAR_3 != 0);



    return 1;



fail:

    if (*VAR_4 && (*VAR_4)->VAR_6 > 0) {

        QLIST_REMOVE(*VAR_4, next_in_flight);

    }

    return VAR_7;

}

static int FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,
uint64_t *VAR_2, uint64_t *VAR_3, QCowL2Meta **VAR_4)
{ BDRVQcowState *s = VAR_0->opaque; int VAR_5; uint64_t *l2_table; uint64_t entry; unsigned int VAR_6; int VAR_7; uint64_t alloc_cluster_offset; trace_qcow2_handle_alloc(qemu_coroutine_self(), VAR_1, *VAR_2,
*VAR_3); assert(*VAR_3 > 0); VAR_6 =
size_to_clusters(s, offset_into_cluster(s, VAR_1) + *VAR_3); VAR_5 = offset_to_l2_index(s, VAR_1); VAR_6 = MIN(VAR_6, s->l2_size - VAR_5); VAR_7 = get_cluster_table(VAR_0, VAR_1, &l2_table, &VAR_5); if (VAR_7 < 0) { return VAR_7; } entry = be64_to_cpu(l2_table[VAR_5]); if (entry & QCOW_OFLAG_COMPRESSED) { VAR_6 = 1; } else { VAR_6 = count_cow_clusters(s, VAR_6, l2_table, VAR_5); } VAR_7 = qcow2_cache_put(VAR_0, s->l2_table_cache, (void**) &l2_table); if (VAR_7 < 0) { return VAR_7; } if (VAR_6 == 0) { *VAR_3 = 0; return 0; } alloc_cluster_offset = start_of_cluster(s, *VAR_2); VAR_7 = do_alloc_cluster_offset(VAR_0, VAR_1, &alloc_cluster_offset,
&VAR_6); if (VAR_7 < 0) { goto fail; } if (VAR_6 == 0) { *VAR_3 = 0; return 0; } int VAR_8 =
(*VAR_3 + offset_into_cluster(s, VAR_1))
>> BDRV_SECTOR_BITS; int VAR_9 = VAR_6
<< (s->cluster_bits - BDRV_SECTOR_BITS); int VAR_10 = offset_into_cluster(s, VAR_1)
>> BDRV_SECTOR_BITS; int VAR_11 = MIN(VAR_8, VAR_9); QCowL2Meta *old_m = *VAR_4; *VAR_4 = g_malloc0(sizeof(**VAR_4)); **VAR_4 = (QCowL2Meta) { .next           = old_m,
.alloc_offset   = alloc_cluster_offset,
.offset         = start_of_cluster(s, VAR_1),
.VAR_6    = VAR_6,
.nb_available   = VAR_11,
.cow_start = { .offset     = 0,
.VAR_11 = VAR_10,
}, .cow_end = { .offset     = VAR_11 * BDRV_SECTOR_SIZE,
.VAR_11 = VAR_9 - VAR_11,
}, }; qemu_co_queue_init(&(*VAR_4)->dependent_requests); QLIST_INSERT_HEAD(&s->cluster_allocs, *VAR_4, next_in_flight); *VAR_2 = alloc_cluster_offset + offset_into_cluster(s, VAR_1); *VAR_3 = MIN(*VAR_3, (VAR_11 * BDRV_SECTOR_SIZE)
- offset_into_cluster(s, VAR_1)); assert(*VAR_3 != 0); return 1; fail:
if (*VAR_4 && (*VAR_4)->VAR_6 > 0) { QLIST_REMOVE(*VAR_4, next_in_flight); } return VAR_7; }