static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,

    uint64_t offset, void **table, bool read_from_disk)

{

    BDRVQcowState *s = bs->opaque;

    int i;

    int ret;

    int lookup_index;

    uint64_t min_lru_counter = UINT64_MAX;

    int min_lru_index = -1;



    trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache,

                          offset, read_from_disk);



    /* Check if the table is already cached */

    i = lookup_index = (offset / s->cluster_size * 4) % c->size;

    do {

        const Qcow2CachedTable *t = &c->entries[i];

        if (t->offset == offset) {

            goto found;

        }

        if (t->ref == 0 && t->lru_counter < min_lru_counter) {

            min_lru_counter = t->lru_counter;

            min_lru_index = i;

        }

        if (++i == c->size) {

            i = 0;

        }

    } while (i != lookup_index);



    if (min_lru_index == -1) {

        /* This can't happen in current synchronous code, but leave the check

         * here as a reminder for whoever starts using AIO with the cache */

        abort();

    }



    /* Cache miss: write a table back and replace it */

    i = min_lru_index;

    trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(),

                                        c == s->l2_table_cache, i);

    if (i < 0) {

        return i;

    }



    ret = qcow2_cache_entry_flush(bs, c, i);

    if (ret < 0) {

        return ret;

    }



    trace_qcow2_cache_get_read(qemu_coroutine_self(),

                               c == s->l2_table_cache, i);

    c->entries[i].offset = 0;

    if (read_from_disk) {

        if (c == s->l2_table_cache) {

            BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);

        }



        ret = bdrv_pread(bs->file, offset, qcow2_cache_get_table_addr(bs, c, i),

                         s->cluster_size);

        if (ret < 0) {

            return ret;

        }

    }



    c->entries[i].offset = offset;



    /* And return the right table */

found:

    c->entries[i].ref++;

    *table = qcow2_cache_get_table_addr(bs, c, i);



    trace_qcow2_cache_get_done(qemu_coroutine_self(),

                               c == s->l2_table_cache, i);



    return 0;

}

static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,

    uint64_t offset, void **table, bool read_from_disk)

{

    BDRVQcowState *s = bs->opaque;

    int i;

    int ret;

    int lookup_index;

    uint64_t min_lru_counter = UINT64_MAX;

    int min_lru_index = -1;



    trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache,

                          offset, read_from_disk);



    

    i = lookup_index = (offset / s->cluster_size * 4) % c->size;

    do {

        const Qcow2CachedTable *t = &c->entries[i];

        if (t->offset == offset) {

            goto found;

        }

        if (t->ref == 0 && t->lru_counter < min_lru_counter) {

            min_lru_counter = t->lru_counter;

            min_lru_index = i;

        }

        if (++i == c->size) {

            i = 0;

        }

    } while (i != lookup_index);



    if (min_lru_index == -1) {

        



        abort();

    }



    

    i = min_lru_index;

    trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(),

                                        c == s->l2_table_cache, i);

    if (i < 0) {

        return i;

    }



    ret = qcow2_cache_entry_flush(bs, c, i);

    if (ret < 0) {

        return ret;

    }



    trace_qcow2_cache_get_read(qemu_coroutine_self(),

                               c == s->l2_table_cache, i);

    c->entries[i].offset = 0;

    if (read_from_disk) {

        if (c == s->l2_table_cache) {

            BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);

        }



        ret = bdrv_pread(bs->file, offset, qcow2_cache_get_table_addr(bs, c, i),

                         s->cluster_size);

        if (ret < 0) {

            return ret;

        }

    }



    c->entries[i].offset = offset;



    

found:

    c->entries[i].ref++;

    *table = qcow2_cache_get_table_addr(bs, c, i);



    trace_qcow2_cache_get_done(qemu_coroutine_self(),

                               c == s->l2_table_cache, i);



    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, Qcow2Cache *VAR_1,

    uint64_t VAR_2, void **VAR_3, bool VAR_4)

{

    BDRVQcowState *s = VAR_0->opaque;

    int VAR_5;

    int VAR_6;

    int VAR_7;

    uint64_t min_lru_counter = UINT64_MAX;

    int VAR_8 = -1;



    trace_qcow2_cache_get(qemu_coroutine_self(), VAR_1 == s->l2_table_cache,

                          VAR_2, VAR_4);



    

    VAR_5 = VAR_7 = (VAR_2 / s->cluster_size * 4) % VAR_1->size;

    do {

        const Qcow2CachedTable *VAR_9 = &VAR_1->entries[VAR_5];

        if (VAR_9->VAR_2 == VAR_2) {

            goto found;

        }

        if (VAR_9->ref == 0 && VAR_9->lru_counter < min_lru_counter) {

            min_lru_counter = VAR_9->lru_counter;

            VAR_8 = VAR_5;

        }

        if (++VAR_5 == VAR_1->size) {

            VAR_5 = 0;

        }

    } while (VAR_5 != VAR_7);



    if (VAR_8 == -1) {

        



        abort();

    }



    

    VAR_5 = VAR_8;

    trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(),

                                        VAR_1 == s->l2_table_cache, VAR_5);

    if (VAR_5 < 0) {

        return VAR_5;

    }



    VAR_6 = qcow2_cache_entry_flush(VAR_0, VAR_1, VAR_5);

    if (VAR_6 < 0) {

        return VAR_6;

    }



    trace_qcow2_cache_get_read(qemu_coroutine_self(),

                               VAR_1 == s->l2_table_cache, VAR_5);

    VAR_1->entries[VAR_5].VAR_2 = 0;

    if (VAR_4) {

        if (VAR_1 == s->l2_table_cache) {

            BLKDBG_EVENT(VAR_0->file, BLKDBG_L2_LOAD);

        }



        VAR_6 = bdrv_pread(VAR_0->file, VAR_2, qcow2_cache_get_table_addr(VAR_0, VAR_1, VAR_5),

                         s->cluster_size);

        if (VAR_6 < 0) {

            return VAR_6;

        }

    }



    VAR_1->entries[VAR_5].VAR_2 = VAR_2;



    

found:

    VAR_1->entries[VAR_5].ref++;

    *VAR_3 = qcow2_cache_get_table_addr(VAR_0, VAR_1, VAR_5);



    trace_qcow2_cache_get_done(qemu_coroutine_self(),

                               VAR_1 == s->l2_table_cache, VAR_5);



    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, Qcow2Cache *VAR_1,
uint64_t VAR_2, void **VAR_3, bool VAR_4)
{ BDRVQcowState *s = VAR_0->opaque; int VAR_5; int VAR_6; int VAR_7; uint64_t min_lru_counter = UINT64_MAX; int VAR_8 = -1; trace_qcow2_cache_get(qemu_coroutine_self(), VAR_1 == s->l2_table_cache,
VAR_2, VAR_4); VAR_5 = VAR_7 = (VAR_2 / s->cluster_size * 4) % VAR_1->size; do { const Qcow2CachedTable *VAR_9 = &VAR_1->entries[VAR_5]; if (VAR_9->VAR_2 == VAR_2) { goto found; } if (VAR_9->ref == 0 && VAR_9->lru_counter < min_lru_counter) { min_lru_counter = VAR_9->lru_counter; VAR_8 = VAR_5; } if (++VAR_5 == VAR_1->size) { VAR_5 = 0; } } while (VAR_5 != VAR_7); if (VAR_8 == -1) { abort(); } VAR_5 = VAR_8; trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(),
VAR_1 == s->l2_table_cache, VAR_5); if (VAR_5 < 0) { return VAR_5; } VAR_6 = qcow2_cache_entry_flush(VAR_0, VAR_1, VAR_5); if (VAR_6 < 0) { return VAR_6; } trace_qcow2_cache_get_read(qemu_coroutine_self(),
VAR_1 == s->l2_table_cache, VAR_5); VAR_1->entries[VAR_5].VAR_2 = 0; if (VAR_4) { if (VAR_1 == s->l2_table_cache) { BLKDBG_EVENT(VAR_0->file, BLKDBG_L2_LOAD); } VAR_6 = bdrv_pread(VAR_0->file, VAR_2, qcow2_cache_get_table_addr(VAR_0, VAR_1, VAR_5),
s->cluster_size); if (VAR_6 < 0) { return VAR_6; } } VAR_1->entries[VAR_5].VAR_2 = VAR_2; found:
VAR_1->entries[VAR_5].ref++; *VAR_3 = qcow2_cache_get_table_addr(VAR_0, VAR_1, VAR_5); trace_qcow2_cache_get_done(qemu_coroutine_self(),
VAR_1 == s->l2_table_cache, VAR_5); return 0; }