static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,

                           uint64_t image_size, VHDXImageType type,

                           bool use_zero_blocks, uint64_t file_offset,

                           uint32_t length)

{

    int ret = 0;

    uint64_t data_file_offset;

    uint64_t total_sectors = 0;

    uint64_t sector_num = 0;

    uint64_t unused;

    int block_state;

    VHDXSectorInfo sinfo;



    assert(s->bat == NULL);



    /* this gives a data start after BAT/bitmap entries, and well

     * past any metadata entries (with a 4 MB buffer for future

     * expansion */

    data_file_offset = file_offset + length + 5 * MiB;

    total_sectors = image_size >> s->logical_sector_size_bits;



    if (type == VHDX_TYPE_DYNAMIC) {

        /* All zeroes, so we can just extend the file - the end of the BAT

         * is the furthest thing we have written yet */

        ret = bdrv_truncate(bs, data_file_offset);

        if (ret < 0) {

            goto exit;

        }

    } else if (type == VHDX_TYPE_FIXED) {

        ret = bdrv_truncate(bs, data_file_offset + image_size);

        if (ret < 0) {

            goto exit;

        }

    } else {

        ret = -ENOTSUP;

        goto exit;

    }



    if (type == VHDX_TYPE_FIXED ||

                use_zero_blocks ||

                bdrv_has_zero_init(bs) == 0) {

        /* for a fixed file, the default BAT entry is not zero */

        s->bat = g_try_malloc0(length);

        if (length && s->bat != NULL) {

            ret = -ENOMEM;

            goto exit;

        }

        block_state = type == VHDX_TYPE_FIXED ? PAYLOAD_BLOCK_FULLY_PRESENT :

                                                PAYLOAD_BLOCK_NOT_PRESENT;

        block_state = use_zero_blocks ? PAYLOAD_BLOCK_ZERO : block_state;

        /* fill the BAT by emulating sector writes of sectors_per_block size */

        while (sector_num < total_sectors) {

            vhdx_block_translate(s, sector_num, s->sectors_per_block, &sinfo);

            sinfo.file_offset = data_file_offset +

                                (sector_num << s->logical_sector_size_bits);

            sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);

            vhdx_update_bat_table_entry(bs, s, &sinfo, &unused, &unused,

                                        block_state);

            cpu_to_le64s(&s->bat[sinfo.bat_idx]);

            sector_num += s->sectors_per_block;

        }

        ret = bdrv_pwrite(bs, file_offset, s->bat, length);

        if (ret < 0) {

            goto exit;

        }

    }







exit:

    g_free(s->bat);

    return ret;

}

static int vhdx_create_bat(BlockDriverState *bs, BDRVVHDXState *s,

                           uint64_t image_size, VHDXImageType type,

                           bool use_zero_blocks, uint64_t file_offset,

                           uint32_t length)

{

    int ret = 0;

    uint64_t data_file_offset;

    uint64_t total_sectors = 0;

    uint64_t sector_num = 0;

    uint64_t unused;

    int block_state;

    VHDXSectorInfo sinfo;



    assert(s->bat == NULL);



    





    data_file_offset = file_offset + length + 5 * MiB;

    total_sectors = image_size >> s->logical_sector_size_bits;



    if (type == VHDX_TYPE_DYNAMIC) {

        



        ret = bdrv_truncate(bs, data_file_offset);

        if (ret < 0) {

            goto exit;

        }

    } else if (type == VHDX_TYPE_FIXED) {

        ret = bdrv_truncate(bs, data_file_offset + image_size);

        if (ret < 0) {

            goto exit;

        }

    } else {

        ret = -ENOTSUP;

        goto exit;

    }



    if (type == VHDX_TYPE_FIXED ||

                use_zero_blocks ||

                bdrv_has_zero_init(bs) == 0) {

        

        s->bat = g_try_malloc0(length);

        if (length && s->bat != NULL) {

            ret = -ENOMEM;

            goto exit;

        }

        block_state = type == VHDX_TYPE_FIXED ? PAYLOAD_BLOCK_FULLY_PRESENT :

                                                PAYLOAD_BLOCK_NOT_PRESENT;

        block_state = use_zero_blocks ? PAYLOAD_BLOCK_ZERO : block_state;

        

        while (sector_num < total_sectors) {

            vhdx_block_translate(s, sector_num, s->sectors_per_block, &sinfo);

            sinfo.file_offset = data_file_offset +

                                (sector_num << s->logical_sector_size_bits);

            sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);

            vhdx_update_bat_table_entry(bs, s, &sinfo, &unused, &unused,

                                        block_state);

            cpu_to_le64s(&s->bat[sinfo.bat_idx]);

            sector_num += s->sectors_per_block;

        }

        ret = bdrv_pwrite(bs, file_offset, s->bat, length);

        if (ret < 0) {

            goto exit;

        }

    }







exit:

    g_free(s->bat);

    return ret;

}

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

                           uint64_t VAR_2, VHDXImageType VAR_3,

                           bool VAR_4, uint64_t VAR_5,

                           uint32_t VAR_6)

{

    int VAR_7 = 0;

    uint64_t data_file_offset;

    uint64_t total_sectors = 0;

    uint64_t sector_num = 0;

    uint64_t unused;

    int VAR_8;

    VHDXSectorInfo sinfo;



    assert(VAR_1->bat == NULL);



    





    data_file_offset = VAR_5 + VAR_6 + 5 * MiB;

    total_sectors = VAR_2 >> VAR_1->logical_sector_size_bits;



    if (VAR_3 == VHDX_TYPE_DYNAMIC) {

        



        VAR_7 = bdrv_truncate(VAR_0, data_file_offset);

        if (VAR_7 < 0) {

            goto exit;

        }

    } else if (VAR_3 == VHDX_TYPE_FIXED) {

        VAR_7 = bdrv_truncate(VAR_0, data_file_offset + VAR_2);

        if (VAR_7 < 0) {

            goto exit;

        }

    } else {

        VAR_7 = -ENOTSUP;

        goto exit;

    }



    if (VAR_3 == VHDX_TYPE_FIXED ||

                VAR_4 ||

                bdrv_has_zero_init(VAR_0) == 0) {

        

        VAR_1->bat = g_try_malloc0(VAR_6);

        if (VAR_6 && VAR_1->bat != NULL) {

            VAR_7 = -ENOMEM;

            goto exit;

        }

        VAR_8 = VAR_3 == VHDX_TYPE_FIXED ? PAYLOAD_BLOCK_FULLY_PRESENT :

                                                PAYLOAD_BLOCK_NOT_PRESENT;

        VAR_8 = VAR_4 ? PAYLOAD_BLOCK_ZERO : VAR_8;

        

        while (sector_num < total_sectors) {

            vhdx_block_translate(VAR_1, sector_num, VAR_1->sectors_per_block, &sinfo);

            sinfo.VAR_5 = data_file_offset +

                                (sector_num << VAR_1->logical_sector_size_bits);

            sinfo.VAR_5 = ROUND_UP(sinfo.VAR_5, MiB);

            vhdx_update_bat_table_entry(VAR_0, VAR_1, &sinfo, &unused, &unused,

                                        VAR_8);

            cpu_to_le64s(&VAR_1->bat[sinfo.bat_idx]);

            sector_num += VAR_1->sectors_per_block;

        }

        VAR_7 = bdrv_pwrite(VAR_0, VAR_5, VAR_1->bat, VAR_6);

        if (VAR_7 < 0) {

            goto exit;

        }

    }







exit:

    g_free(VAR_1->bat);

    return VAR_7;

}

static int FUNC_0(BlockDriverState *VAR_0, BDRVVHDXState *VAR_1,
uint64_t VAR_2, VHDXImageType VAR_3,
bool VAR_4, uint64_t VAR_5,
uint32_t VAR_6)
{ int VAR_7 = 0; uint64_t data_file_offset; uint64_t total_sectors = 0; uint64_t sector_num = 0; uint64_t unused; int VAR_8; VHDXSectorInfo sinfo; assert(VAR_1->bat == NULL); data_file_offset = VAR_5 + VAR_6 + 5 * MiB; total_sectors = VAR_2 >> VAR_1->logical_sector_size_bits; if (VAR_3 == VHDX_TYPE_DYNAMIC) { VAR_7 = bdrv_truncate(VAR_0, data_file_offset); if (VAR_7 < 0) { goto exit; } } else if (VAR_3 == VHDX_TYPE_FIXED) { VAR_7 = bdrv_truncate(VAR_0, data_file_offset + VAR_2); if (VAR_7 < 0) { goto exit; } } else { VAR_7 = -ENOTSUP; goto exit; } if (VAR_3 == VHDX_TYPE_FIXED ||
VAR_4 ||
bdrv_has_zero_init(VAR_0) == 0) { VAR_1->bat = g_try_malloc0(VAR_6); if (VAR_6 && VAR_1->bat != NULL) { VAR_7 = -ENOMEM; goto exit; } VAR_8 = VAR_3 == VHDX_TYPE_FIXED ? PAYLOAD_BLOCK_FULLY_PRESENT :
PAYLOAD_BLOCK_NOT_PRESENT; VAR_8 = VAR_4 ? PAYLOAD_BLOCK_ZERO : VAR_8; while (sector_num < total_sectors) { vhdx_block_translate(VAR_1, sector_num, VAR_1->sectors_per_block, &sinfo); sinfo.VAR_5 = data_file_offset +
(sector_num << VAR_1->logical_sector_size_bits); sinfo.VAR_5 = ROUND_UP(sinfo.VAR_5, MiB); vhdx_update_bat_table_entry(VAR_0, VAR_1, &sinfo, &unused, &unused,
VAR_8); cpu_to_le64s(&VAR_1->bat[sinfo.bat_idx]); sector_num += VAR_1->sectors_per_block; } VAR_7 = bdrv_pwrite(VAR_0, VAR_5, VAR_1->bat, VAR_6); if (VAR_7 < 0) { goto exit; } } exit:
g_free(VAR_1->bat); return VAR_7; }