static int discard_single_l2(BlockDriverState *bs, uint64_t offset,

                             uint64_t nb_clusters, enum qcow2_discard_type type,

                             bool full_discard)

{

    BDRVQcow2State *s = bs->opaque;

    uint64_t *l2_table;

    int l2_index;

    int ret;

    int i;



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

    if (ret < 0) {

        return ret;

    }



    /* Limit nb_clusters to one L2 table */

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

    assert(nb_clusters <= INT_MAX);



    for (i = 0; i < nb_clusters; i++) {

        uint64_t old_l2_entry;



        old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);



        /*

         * If full_discard is false, make sure that a discarded area reads back

         * as zeroes for v3 images (we cannot do it for v2 without actually

         * writing a zero-filled buffer). We can skip the operation if the

         * cluster is already marked as zero, or if it's unallocated and we

         * don't have a backing file.

         *

         * TODO We might want to use bdrv_get_block_status(bs) here, but we're

         * holding s->lock, so that doesn't work today.

         *

         * If full_discard is true, the sector should not read back as zeroes,

         * but rather fall through to the backing file.

         */

        switch (qcow2_get_cluster_type(old_l2_entry)) {

        case QCOW2_CLUSTER_UNALLOCATED:

            if (full_discard || !bs->backing) {

                continue;

            }

            break;



        case QCOW2_CLUSTER_ZERO_PLAIN:

            if (!full_discard) {

                continue;

            }

            break;



        case QCOW2_CLUSTER_ZERO_ALLOC:

        case QCOW2_CLUSTER_NORMAL:

        case QCOW2_CLUSTER_COMPRESSED:

            break;



        default:

            abort();

        }



        /* First remove L2 entries */

        qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);

        if (!full_discard && s->qcow_version >= 3) {

            l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);

        } else {

            l2_table[l2_index + i] = cpu_to_be64(0);

        }



        /* Then decrease the refcount */

        qcow2_free_any_clusters(bs, old_l2_entry, 1, type);

    }



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



    return nb_clusters;

}

static int discard_single_l2(BlockDriverState *bs, uint64_t offset,

                             uint64_t nb_clusters, enum qcow2_discard_type type,

                             bool full_discard)

{

    BDRVQcow2State *s = bs->opaque;

    uint64_t *l2_table;

    int l2_index;

    int ret;

    int i;



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

    if (ret < 0) {

        return ret;

    }



    

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

    assert(nb_clusters <= INT_MAX);



    for (i = 0; i < nb_clusters; i++) {

        uint64_t old_l2_entry;



        old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);



        

























        switch (qcow2_get_cluster_type(old_l2_entry)) {

        case QCOW2_CLUSTER_UNALLOCATED:

            if (full_discard || !bs->backing) {

                continue;

            }

            break;



        case QCOW2_CLUSTER_ZERO_PLAIN:

            if (!full_discard) {

                continue;

            }

            break;



        case QCOW2_CLUSTER_ZERO_ALLOC:

        case QCOW2_CLUSTER_NORMAL:

        case QCOW2_CLUSTER_COMPRESSED:

            break;



        default:

            abort();

        }



        

        qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache, l2_table);

        if (!full_discard && s->qcow_version >= 3) {

            l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);

        } else {

            l2_table[l2_index + i] = cpu_to_be64(0);

        }



        

        qcow2_free_any_clusters(bs, old_l2_entry, 1, type);

    }



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



    return nb_clusters;

}

static int FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,

                             uint64_t VAR_2, enum qcow2_discard_type VAR_3,

                             bool VAR_4)

{

    BDRVQcow2State *s = VAR_0->opaque;

    uint64_t *l2_table;

    int VAR_5;

    int VAR_6;

    int VAR_7;



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

    if (VAR_6 < 0) {

        return VAR_6;

    }



    

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

    assert(VAR_2 <= INT_MAX);



    for (VAR_7 = 0; VAR_7 < VAR_2; VAR_7++) {

        uint64_t old_l2_entry;



        old_l2_entry = be64_to_cpu(l2_table[VAR_5 + VAR_7]);



        

























        switch (qcow2_get_cluster_type(old_l2_entry)) {

        case QCOW2_CLUSTER_UNALLOCATED:

            if (VAR_4 || !VAR_0->backing) {

                continue;

            }

            break;



        case QCOW2_CLUSTER_ZERO_PLAIN:

            if (!VAR_4) {

                continue;

            }

            break;



        case QCOW2_CLUSTER_ZERO_ALLOC:

        case QCOW2_CLUSTER_NORMAL:

        case QCOW2_CLUSTER_COMPRESSED:

            break;



        default:

            abort();

        }



        

        qcow2_cache_entry_mark_dirty(VAR_0, s->l2_table_cache, l2_table);

        if (!VAR_4 && s->qcow_version >= 3) {

            l2_table[VAR_5 + VAR_7] = cpu_to_be64(QCOW_OFLAG_ZERO);

        } else {

            l2_table[VAR_5 + VAR_7] = cpu_to_be64(0);

        }



        

        qcow2_free_any_clusters(VAR_0, old_l2_entry, 1, VAR_3);

    }



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



    return VAR_2;

}

static int FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,
uint64_t VAR_2, enum qcow2_discard_type VAR_3,
bool VAR_4)
{ BDRVQcow2State *s = VAR_0->opaque; uint64_t *l2_table; int VAR_5; int VAR_6; int VAR_7; VAR_6 = get_cluster_table(VAR_0, VAR_1, &l2_table, &VAR_5); if (VAR_6 < 0) { return VAR_6; } VAR_2 = MIN(VAR_2, s->l2_size - VAR_5); assert(VAR_2 <= INT_MAX); for (VAR_7 = 0; VAR_7 < VAR_2; VAR_7++) { uint64_t old_l2_entry; old_l2_entry = be64_to_cpu(l2_table[VAR_5 + VAR_7]); switch (qcow2_get_cluster_type(old_l2_entry)) { case QCOW2_CLUSTER_UNALLOCATED:
if (VAR_4 || !VAR_0->backing) { continue; } break; case QCOW2_CLUSTER_ZERO_PLAIN:
if (!VAR_4) { continue; } break; case QCOW2_CLUSTER_ZERO_ALLOC:
case QCOW2_CLUSTER_NORMAL:
case QCOW2_CLUSTER_COMPRESSED:
break; default:
abort(); } qcow2_cache_entry_mark_dirty(VAR_0, s->l2_table_cache, l2_table); if (!VAR_4 && s->qcow_version >= 3) { l2_table[VAR_5 + VAR_7] = cpu_to_be64(QCOW_OFLAG_ZERO); } else { l2_table[VAR_5 + VAR_7] = cpu_to_be64(0); } qcow2_free_any_clusters(VAR_0, old_l2_entry, 1, VAR_3); } qcow2_cache_put(VAR_0, s->l2_table_cache, (void **) &l2_table); return VAR_2; }