[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 31/36] block: vhdx - break out code operations to fun
From: |
Stefan Hajnoczi |
Subject: |
[Qemu-devel] [PULL 31/36] block: vhdx - break out code operations to functions |
Date: |
Thu, 7 Nov 2013 14:12:39 +0100 |
From: Jeff Cody <address@hidden>
This is preperation for vhdx_create(). The ability to write headers,
and calculate the number of BAT entries will be needed within the
create() functions, so move this relevant code into helper functions.
Signed-off-by: Jeff Cody <address@hidden>
Signed-off-by: Stefan Hajnoczi <address@hidden>
---
block/vhdx.c | 121 +++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 80 insertions(+), 41 deletions(-)
diff --git a/block/vhdx.c b/block/vhdx.c
index 7da149a..7bf7cd6 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -248,6 +248,14 @@ static void vhdx_region_unregister_all(BDRVVHDXState *s)
}
}
+static void vhdx_set_shift_bits(BDRVVHDXState *s)
+{
+ s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
+ s->sectors_per_block_bits = 31 - clz32(s->sectors_per_block);
+ s->chunk_ratio_bits = 63 - clz64(s->chunk_ratio);
+ s->block_size_bits = 31 - clz32(s->block_size);
+}
+
/*
* Per the MS VHDX Specification, for every VHDX file:
* - The header section is fixed size - 1 MB
@@ -267,6 +275,50 @@ static int vhdx_probe(const uint8_t *buf, int buf_size,
const char *filename)
return 0;
}
+/*
+ * Writes the header to the specified offset.
+ *
+ * This will optionally read in buffer data from disk (otherwise zero-fill),
+ * and then update the header checksum. Header is converted to proper
+ * endianness before being written to the specified file offset
+ */
+static int vhdx_write_header(BlockDriverState *bs_file, VHDXHeader *hdr,
+ uint64_t offset, bool read)
+{
+ uint8_t *buffer = NULL;
+ int ret;
+ VHDXHeader header_le;
+
+ assert(bs_file != NULL);
+ assert(hdr != NULL);
+
+ /* the header checksum is not over just the packed size of VHDXHeader,
+ * but rather over the entire 'reserved' range for the header, which is
+ * 4KB (VHDX_HEADER_SIZE). */
+
+ buffer = qemu_blockalign(bs_file, VHDX_HEADER_SIZE);
+ if (read) {
+ /* if true, we can't assume the extra reserved bytes are 0 */
+ ret = bdrv_pread(bs_file, offset, buffer, VHDX_HEADER_SIZE);
+ if (ret < 0) {
+ goto exit;
+ }
+ } else {
+ memset(buffer, 0, VHDX_HEADER_SIZE);
+ }
+
+ /* overwrite the actual VHDXHeader portion */
+ memcpy(buffer, hdr, sizeof(VHDXHeader));
+ hdr->checksum = vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
+ offsetof(VHDXHeader, checksum));
+ vhdx_header_le_export(hdr, &header_le);
+ ret = bdrv_pwrite_sync(bs_file, offset, &header_le, sizeof(VHDXHeader));
+
+exit:
+ qemu_vfree(buffer);
+ return ret;
+}
+
/* Update the VHDX headers
*
* This follows the VHDX spec procedures for header updates.
@@ -282,8 +334,6 @@ static int vhdx_update_header(BlockDriverState *bs,
BDRVVHDXState *s,
VHDXHeader *active_header;
VHDXHeader *inactive_header;
- VHDXHeader header_le;
- uint8_t *buffer;
/* operate on the non-current header */
if (s->curr_header == 0) {
@@ -311,31 +361,13 @@ static int vhdx_update_header(BlockDriverState *bs,
BDRVVHDXState *s,
inactive_header->log_guid = *log_guid;
}
- /* the header checksum is not over just the packed size of VHDXHeader,
- * but rather over the entire 'reserved' range for the header, which is
- * 4KB (VHDX_HEADER_SIZE). */
-
- buffer = qemu_blockalign(bs, VHDX_HEADER_SIZE);
- /* we can't assume the extra reserved bytes are 0 */
- ret = bdrv_pread(bs->file, header_offset, buffer, VHDX_HEADER_SIZE);
- if (ret < 0) {
- goto exit;
- }
- /* overwrite the actual VHDXHeader portion */
- memcpy(buffer, inactive_header, sizeof(VHDXHeader));
- inactive_header->checksum =
- vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
- offsetof(VHDXHeader, checksum));
- vhdx_header_le_export(inactive_header, &header_le);
- ret = bdrv_pwrite_sync(bs->file, header_offset, &header_le,
- sizeof(VHDXHeader));
+ vhdx_write_header(bs->file, inactive_header, header_offset, true);
if (ret < 0) {
goto exit;
}
s->curr_header = hdr_idx;
exit:
- qemu_vfree(buffer);
return ret;
}
@@ -773,10 +805,7 @@ static int vhdx_parse_metadata(BlockDriverState *bs,
BDRVVHDXState *s)
goto exit;
}
- s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
- s->sectors_per_block_bits = 31 - clz32(s->sectors_per_block);
- s->chunk_ratio_bits = 63 - clz64(s->chunk_ratio);
- s->block_size_bits = 31 - clz32(s->block_size);
+ vhdx_set_shift_bits(s);
ret = 0;
@@ -785,6 +814,31 @@ exit:
return ret;
}
+/*
+ * Calculate the number of BAT entries, including sector
+ * bitmap entries.
+ */
+static void vhdx_calc_bat_entries(BDRVVHDXState *s)
+{
+ uint32_t data_blocks_cnt, bitmap_blocks_cnt;
+
+ data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;
+ if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {
+ data_blocks_cnt++;
+ }
+ bitmap_blocks_cnt = data_blocks_cnt >> s->chunk_ratio_bits;
+ if (data_blocks_cnt - (bitmap_blocks_cnt << s->chunk_ratio_bits)) {
+ bitmap_blocks_cnt++;
+ }
+
+ if (s->parent_entries) {
+ s->bat_entries = bitmap_blocks_cnt * (s->chunk_ratio + 1);
+ } else {
+ s->bat_entries = data_blocks_cnt +
+ ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);
+ }
+
+}
static void vhdx_close(BlockDriverState *bs)
{
@@ -811,7 +865,6 @@ static int vhdx_open(BlockDriverState *bs, QDict *options,
int flags,
int ret = 0;
uint32_t i;
uint64_t signature;
- uint32_t data_blocks_cnt, bitmap_blocks_cnt;
bool log_flushed = false;
@@ -862,21 +915,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options,
int flags,
* logical_sector_size */
bs->total_sectors = s->virtual_disk_size >> s->logical_sector_size_bits;
- data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;
- if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {
- data_blocks_cnt++;
- }
- bitmap_blocks_cnt = data_blocks_cnt >> s->chunk_ratio_bits;
- if (data_blocks_cnt - (bitmap_blocks_cnt << s->chunk_ratio_bits)) {
- bitmap_blocks_cnt++;
- }
-
- if (s->parent_entries) {
- s->bat_entries = bitmap_blocks_cnt * (s->chunk_ratio + 1);
- } else {
- s->bat_entries = data_blocks_cnt +
- ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);
- }
+ vhdx_calc_bat_entries(s);
s->bat_offset = s->bat_rt.file_offset;
--
1.8.3.1
- [Qemu-devel] [PULL 33/36] block: vhdx - add .bdrv_create() support, (continued)
- [Qemu-devel] [PULL 33/36] block: vhdx - add .bdrv_create() support, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 25/36] block: vhdx - log parsing, replay, and flush support, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 29/36] block: vhdx - remove BAT file offset bit shifting, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 27/36] block: vhdx - add log write support, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 24/36] block: vhdx code movement - move vhdx_close() above vhdx_open(), Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 19/36] block: vhdx - add header update capability., Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 21/36] block: vhdx - log support struct and defines, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 23/36] block: vhdx - update log guid in header, and first write tracker, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 02/36] qemu-iotests: Filter out actual image size in 067, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 30/36] block: vhdx - move more endian translations to vhdx-endian.c, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 31/36] block: vhdx - break out code operations to functions,
Stefan Hajnoczi <=
- [Qemu-devel] [PULL 32/36] block: vhdx - fix comment typos in header, fix incorrect struct fields, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 36/36] block: vhdx qemu-iotest - log replay of data sector, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 18/36] block: vhdx - minor comments and typo correction., Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 06/36] block: qemu-iotests, add quotes to $TEST_IMG.base usage in 017, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 17/36] block/vpc: fix virtual size for images created with disk2vhd, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 09/36] block: qemu-iotests, add quotes to $TEST_IMG usage for 051, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 11/36] blockdev: fix drive_init() opts and bs_opts leaks, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 28/36] block: vhdx write support, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 16/36] block: Save errno before error_setg_errno, Stefan Hajnoczi, 2013/11/07
- [Qemu-devel] [PULL 15/36] qdev-monitor-test: add device_add leak test cases, Stefan Hajnoczi, 2013/11/07