static uint64_t *store_bitmap_data(BlockDriverState *bs,

                                   BdrvDirtyBitmap *bitmap,

                                   uint32_t *bitmap_table_size, Error **errp)

{

    int ret;

    BDRVQcow2State *s = bs->opaque;

    int64_t sector;

    uint64_t limit, sbc;

    uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);

    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);

    const char *bm_name = bdrv_dirty_bitmap_name(bitmap);

    uint8_t *buf = NULL;

    BdrvDirtyBitmapIter *dbi;

    uint64_t *tb;

    uint64_t tb_size =

            size_to_clusters(s,

                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));



    if (tb_size > BME_MAX_TABLE_SIZE ||

        tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)

    {

        error_setg(errp, "Bitmap '%s' is too big", bm_name);

        return NULL;

    }



    tb = g_try_new0(uint64_t, tb_size);

    if (tb == NULL) {

        error_setg(errp, "No memory");

        return NULL;

    }



    dbi = bdrv_dirty_iter_new(bitmap);

    buf = g_malloc(s->cluster_size);

    limit = bytes_covered_by_bitmap_cluster(s, bitmap);

    sbc = limit >> BDRV_SECTOR_BITS;

    assert(DIV_ROUND_UP(bm_size, limit) == tb_size);



    while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) >= 0) {

        uint64_t cluster = sector / sbc;

        uint64_t end, write_size;

        int64_t off;



        sector = cluster * sbc;

        end = MIN(bm_sectors, sector + sbc);

        write_size = bdrv_dirty_bitmap_serialization_size(bitmap,

            sector * BDRV_SECTOR_SIZE, (end - sector) * BDRV_SECTOR_SIZE);

        assert(write_size <= s->cluster_size);



        off = qcow2_alloc_clusters(bs, s->cluster_size);

        if (off < 0) {

            error_setg_errno(errp, -off,

                             "Failed to allocate clusters for bitmap '%s'",

                             bm_name);

            goto fail;

        }

        tb[cluster] = off;



        bdrv_dirty_bitmap_serialize_part(bitmap, buf,

                                         sector * BDRV_SECTOR_SIZE,

                                         (end - sector) * BDRV_SECTOR_SIZE);

        if (write_size < s->cluster_size) {

            memset(buf + write_size, 0, s->cluster_size - write_size);

        }



        ret = qcow2_pre_write_overlap_check(bs, 0, off, s->cluster_size);

        if (ret < 0) {

            error_setg_errno(errp, -ret, "Qcow2 overlap check failed");

            goto fail;

        }



        ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size);

        if (ret < 0) {

            error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",

                             bm_name);

            goto fail;

        }



        if (end >= bm_sectors) {

            break;

        }



        bdrv_set_dirty_iter(dbi, end * BDRV_SECTOR_SIZE);

    }



    *bitmap_table_size = tb_size;

    g_free(buf);

    bdrv_dirty_iter_free(dbi);



    return tb;



fail:

    clear_bitmap_table(bs, tb, tb_size);

    g_free(buf);

    bdrv_dirty_iter_free(dbi);

    g_free(tb);



    return NULL;

}

static uint64_t *store_bitmap_data(BlockDriverState *bs,

                                   BdrvDirtyBitmap *bitmap,

                                   uint32_t *bitmap_table_size, Error **errp)

{

    int ret;

    BDRVQcow2State *s = bs->opaque;

    int64_t sector;

    uint64_t limit, sbc;

    uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);

    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);

    const char *bm_name = bdrv_dirty_bitmap_name(bitmap);

    uint8_t *buf = NULL;

    BdrvDirtyBitmapIter *dbi;

    uint64_t *tb;

    uint64_t tb_size =

            size_to_clusters(s,

                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));



    if (tb_size > BME_MAX_TABLE_SIZE ||

        tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)

    {

        error_setg(errp, "Bitmap '%s' is too big", bm_name);

        return NULL;

    }



    tb = g_try_new0(uint64_t, tb_size);

    if (tb == NULL) {

        error_setg(errp, "No memory");

        return NULL;

    }



    dbi = bdrv_dirty_iter_new(bitmap);

    buf = g_malloc(s->cluster_size);

    limit = bytes_covered_by_bitmap_cluster(s, bitmap);

    sbc = limit >> BDRV_SECTOR_BITS;

    assert(DIV_ROUND_UP(bm_size, limit) == tb_size);



    while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) >= 0) {

        uint64_t cluster = sector / sbc;

        uint64_t end, write_size;

        int64_t off;



        sector = cluster * sbc;

        end = MIN(bm_sectors, sector + sbc);

        write_size = bdrv_dirty_bitmap_serialization_size(bitmap,

            sector * BDRV_SECTOR_SIZE, (end - sector) * BDRV_SECTOR_SIZE);

        assert(write_size <= s->cluster_size);



        off = qcow2_alloc_clusters(bs, s->cluster_size);

        if (off < 0) {

            error_setg_errno(errp, -off,

                             "Failed to allocate clusters for bitmap '%s'",

                             bm_name);

            goto fail;

        }

        tb[cluster] = off;



        bdrv_dirty_bitmap_serialize_part(bitmap, buf,

                                         sector * BDRV_SECTOR_SIZE,

                                         (end - sector) * BDRV_SECTOR_SIZE);

        if (write_size < s->cluster_size) {

            memset(buf + write_size, 0, s->cluster_size - write_size);

        }



        ret = qcow2_pre_write_overlap_check(bs, 0, off, s->cluster_size);

        if (ret < 0) {

            error_setg_errno(errp, -ret, "Qcow2 overlap check failed");

            goto fail;

        }



        ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size);

        if (ret < 0) {

            error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",

                             bm_name);

            goto fail;

        }



        if (end >= bm_sectors) {

            break;

        }



        bdrv_set_dirty_iter(dbi, end * BDRV_SECTOR_SIZE);

    }



    *bitmap_table_size = tb_size;

    g_free(buf);

    bdrv_dirty_iter_free(dbi);



    return tb;



fail:

    clear_bitmap_table(bs, tb, tb_size);

    g_free(buf);

    bdrv_dirty_iter_free(dbi);

    g_free(tb);



    return NULL;

}

static uint64_t *FUNC_0(BlockDriverState *bs,

                                   BdrvDirtyBitmap *bitmap,

                                   uint32_t *bitmap_table_size, Error **errp)

{

    int VAR_0;

    BDRVQcow2State *s = bs->opaque;

    int64_t sector;

    uint64_t limit, sbc;

    uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);

    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);

    const char *VAR_1 = bdrv_dirty_bitmap_name(bitmap);

    uint8_t *buf = NULL;

    BdrvDirtyBitmapIter *dbi;

    uint64_t *tb;

    uint64_t tb_size =

            size_to_clusters(s,

                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));



    if (tb_size > BME_MAX_TABLE_SIZE ||

        tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)

    {

        error_setg(errp, "Bitmap '%s' is too big", VAR_1);

        return NULL;

    }



    tb = g_try_new0(uint64_t, tb_size);

    if (tb == NULL) {

        error_setg(errp, "No memory");

        return NULL;

    }



    dbi = bdrv_dirty_iter_new(bitmap);

    buf = g_malloc(s->cluster_size);

    limit = bytes_covered_by_bitmap_cluster(s, bitmap);

    sbc = limit >> BDRV_SECTOR_BITS;

    assert(DIV_ROUND_UP(bm_size, limit) == tb_size);



    while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) >= 0) {

        uint64_t cluster = sector / sbc;

        uint64_t end, write_size;

        int64_t off;



        sector = cluster * sbc;

        end = MIN(bm_sectors, sector + sbc);

        write_size = bdrv_dirty_bitmap_serialization_size(bitmap,

            sector * BDRV_SECTOR_SIZE, (end - sector) * BDRV_SECTOR_SIZE);

        assert(write_size <= s->cluster_size);



        off = qcow2_alloc_clusters(bs, s->cluster_size);

        if (off < 0) {

            error_setg_errno(errp, -off,

                             "Failed to allocate clusters for bitmap '%s'",

                             VAR_1);

            goto fail;

        }

        tb[cluster] = off;



        bdrv_dirty_bitmap_serialize_part(bitmap, buf,

                                         sector * BDRV_SECTOR_SIZE,

                                         (end - sector) * BDRV_SECTOR_SIZE);

        if (write_size < s->cluster_size) {

            memset(buf + write_size, 0, s->cluster_size - write_size);

        }



        VAR_0 = qcow2_pre_write_overlap_check(bs, 0, off, s->cluster_size);

        if (VAR_0 < 0) {

            error_setg_errno(errp, -VAR_0, "Qcow2 overlap check failed");

            goto fail;

        }



        VAR_0 = bdrv_pwrite(bs->file, off, buf, s->cluster_size);

        if (VAR_0 < 0) {

            error_setg_errno(errp, -VAR_0, "Failed to write bitmap '%s' to file",

                             VAR_1);

            goto fail;

        }



        if (end >= bm_sectors) {

            break;

        }



        bdrv_set_dirty_iter(dbi, end * BDRV_SECTOR_SIZE);

    }



    *bitmap_table_size = tb_size;

    g_free(buf);

    bdrv_dirty_iter_free(dbi);



    return tb;



fail:

    clear_bitmap_table(bs, tb, tb_size);

    g_free(buf);

    bdrv_dirty_iter_free(dbi);

    g_free(tb);



    return NULL;

}

static uint64_t *FUNC_0(BlockDriverState *bs,
BdrvDirtyBitmap *bitmap,
uint32_t *bitmap_table_size, Error **errp)
{ int VAR_0; BDRVQcow2State *s = bs->opaque; int64_t sector; uint64_t limit, sbc; uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap); uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE); const char *VAR_1 = bdrv_dirty_bitmap_name(bitmap); uint8_t *buf = NULL; BdrvDirtyBitmapIter *dbi; uint64_t *tb; uint64_t tb_size =
size_to_clusters(s,
bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size)); if (tb_size > BME_MAX_TABLE_SIZE ||
tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)
{ error_setg(errp, "Bitmap '%s' is too big", VAR_1); return NULL; } tb = g_try_new0(uint64_t, tb_size); if (tb == NULL) { error_setg(errp, "No memory"); return NULL; } dbi = bdrv_dirty_iter_new(bitmap); buf = g_malloc(s->cluster_size); limit = bytes_covered_by_bitmap_cluster(s, bitmap); sbc = limit >> BDRV_SECTOR_BITS; assert(DIV_ROUND_UP(bm_size, limit) == tb_size); while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) >= 0) { uint64_t cluster = sector / sbc; uint64_t end, write_size; int64_t off; sector = cluster * sbc; end = MIN(bm_sectors, sector + sbc); write_size = bdrv_dirty_bitmap_serialization_size(bitmap,
sector * BDRV_SECTOR_SIZE, (end - sector) * BDRV_SECTOR_SIZE); assert(write_size <= s->cluster_size); off = qcow2_alloc_clusters(bs, s->cluster_size); if (off < 0) { error_setg_errno(errp, -off,
"Failed to allocate clusters for bitmap '%s'",
VAR_1); goto fail; } tb[cluster] = off; bdrv_dirty_bitmap_serialize_part(bitmap, buf,
sector * BDRV_SECTOR_SIZE,
(end - sector) * BDRV_SECTOR_SIZE); if (write_size < s->cluster_size) { memset(buf + write_size, 0, s->cluster_size - write_size); } VAR_0 = qcow2_pre_write_overlap_check(bs, 0, off, s->cluster_size); if (VAR_0 < 0) { error_setg_errno(errp, -VAR_0, "Qcow2 overlap check failed"); goto fail; } VAR_0 = bdrv_pwrite(bs->file, off, buf, s->cluster_size); if (VAR_0 < 0) { error_setg_errno(errp, -VAR_0, "Failed to write bitmap '%s' to file",
VAR_1); goto fail; } if (end >= bm_sectors) { break; } bdrv_set_dirty_iter(dbi, end * BDRV_SECTOR_SIZE); } *bitmap_table_size = tb_size; g_free(buf); bdrv_dirty_iter_free(dbi); return tb; fail:
clear_bitmap_table(bs, tb, tb_size); g_free(buf); bdrv_dirty_iter_free(dbi); g_free(tb); return NULL; }