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);
    /* This function is only called when there were no non-COW clusters, so if
     * we can't find any unallocated or COW clusters either, something is
     * wrong with our code. */
    assert(nb_clusters > 0);
    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
    if (ret < 0) {
        return ret;
    /* 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) {
    /* 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);
    


    assert(nb_clusters > 0);
    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
    if (ret < 0) {
        return ret;
    
    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) {
    
    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;
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);
    


    assert(VAR_6 > 0);
    VAR_7 = qcow2_cache_put(VAR_0, s->l2_table_cache, (void**) &l2_table);
    if (VAR_7 < 0) {
        return VAR_7;
    
    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) {
    
    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); assert(VAR_6 > 0); VAR_7 = qcow2_cache_put(VAR_0, s->l2_table_cache, (void**) &l2_table); if (VAR_7 < 0) { return VAR_7; 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) { 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;