static int vhdx_create_new_region_table(BlockDriverState *bs,
                                        uint64_t image_size,
                                        uint32_t block_size,
                                        uint32_t sector_size,
                                        uint32_t log_size,
                                        bool use_zero_blocks,
                                        VHDXImageType type,
                                        uint64_t *metadata_offset)
{
    int ret = 0;
    uint32_t offset = 0;
    void *buffer = NULL;
    BDRVVHDXState *s = NULL;
    VHDXRegionTableHeader *region_table;
    VHDXRegionTableEntry *rt_bat;
    VHDXRegionTableEntry *rt_metadata;

    assert(metadata_offset != NULL);

    /* Populate enough of the BDRVVHDXState to be able to use the
     * pre-existing BAT calculation, translation, and update functions */
    s = g_malloc0(sizeof(BDRVVHDXState));

    s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
                     (uint64_t) sector_size / (uint64_t) block_size;

    s->sectors_per_block = block_size / sector_size;
    s->virtual_disk_size = image_size;
    s->block_size = block_size;
    s->logical_sector_size = sector_size;

    vhdx_set_shift_bits(s);

    vhdx_calc_bat_entries(s);

    /* At this point the VHDX state is populated enough for creation */

    /* a single buffer is used so we can calculate the checksum over the
     * entire 64KB block */
    buffer = g_malloc0(VHDX_HEADER_BLOCK_SIZE);
    region_table = buffer;
    offset += sizeof(VHDXRegionTableHeader);
    rt_bat = buffer + offset;
    offset += sizeof(VHDXRegionTableEntry);
    rt_metadata  = buffer + offset;

    region_table->signature = VHDX_REGION_SIGNATURE;
    region_table->entry_count = 2;   /* BAT and Metadata */

    rt_bat->guid        = bat_guid;
    rt_bat->length      = ROUND_UP(s->bat_entries * sizeof(VHDXBatEntry), MiB);
    rt_bat->file_offset = ROUND_UP(VHDX_HEADER_SECTION_END + log_size, MiB);
    s->bat_offset = rt_bat->file_offset;

    rt_metadata->guid        = metadata_guid;
    rt_metadata->file_offset = ROUND_UP(rt_bat->file_offset + rt_bat->length,
                                        MiB);
    rt_metadata->length      = 1 * MiB; /* min size, and more than enough */
    *metadata_offset = rt_metadata->file_offset;

    vhdx_update_checksum(buffer, VHDX_HEADER_BLOCK_SIZE,
                         offsetof(VHDXRegionTableHeader, checksum));


    /* The region table gives us the data we need to create the BAT,
     * so do that now */
    ret = vhdx_create_bat(bs, s, image_size, type, use_zero_blocks, rt_bat);

    /* Now write out the region headers to disk */
    vhdx_region_header_le_export(region_table);
    vhdx_region_entry_le_export(rt_bat);
    vhdx_region_entry_le_export(rt_metadata);

    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE_OFFSET, buffer,
                      VHDX_HEADER_BLOCK_SIZE);
    if (ret < 0) {
        goto exit;
    }

    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE2_OFFSET, buffer,
                      VHDX_HEADER_BLOCK_SIZE);
    if (ret < 0) {
        goto exit;
    }


exit:
    g_free(s);
    g_free(buffer);
    return ret;
}
Unknown