static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
    uint64_t offset, void **table, bool read_from_disk)
{
    BDRVQcow2State *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);
    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)
{
    BDRVQcow2State *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);
    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)
{
    BDRVQcow2State *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 *t = &VAR_1->entries[VAR_5];
        if (t->VAR_2 == VAR_2) {
            goto found;
        if (t->ref == 0 && t->lru_counter < min_lru_counter) {
            min_lru_counter = t->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);
    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)
{ BDRVQcow2State *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 *t = &VAR_1->entries[VAR_5]; if (t->VAR_2 == VAR_2) { goto found; if (t->ref == 0 && t->lru_counter < min_lru_counter) { min_lru_counter = t->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); 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;