BDRV_SECTOR_SIZE is replaced by VHD_SECTOR_SIZE when the sector size is VHD specific.
Signed-off-by: Stefan Weil <s...@weilnetz.de> --- block/vpc.c | 59 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index e8968c2..8434a91 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -37,6 +37,20 @@ #define FOOTER_SIZE 512 +/* By default, VHD uses a block size of 2 MiB for dynamic disk images. */ +#define VHD_DEFAULT_BLOCK_SIZE 0x200000 + +/* VHD uses linked data structures with 64 bit links. + * 0xffffffffffffffff terminates the chain. + * Note: The spec is actually wrong here for data_offset, it says + * 0xffffffff, but MS tools expect all 64 bits to be set. */ +#define VHD_NO_NEXT UINT64_MAX + +/* Last entry in page table. */ +#define VHD_NO_PAGE UINT32_MAX + +#define VHD_SECTOR_SIZE 512 + //#define CACHE enum vhd_type { @@ -54,7 +68,7 @@ struct vhd_footer { uint32_t features; uint32_t version; - // Offset of next header structure, 0xFFFFFFFF if none + /* Offset of next header structure or VHD_NO_NEXT */ uint64_t data_offset; // Seconds since Jan 1, 2000 0:00:00 (UTC) @@ -87,7 +101,7 @@ struct vhd_footer { struct vhd_dyndisk_header { char magic[8]; // "cxsparse" - // Offset of next header structure, 0xFFFFFFFF if none + /* Offset of next header structure or VHD_NO_NEXT */ uint64_t data_offset; // Offset of the Block Allocation Table (BAT) @@ -201,7 +215,7 @@ static int vpc_open(BlockDriverState *bs, int flags) /* The visible size of an image in Virtual PC may depend on the geometry * rather than on the size stored in the footer (the size in the footer * is usually larger). Nevertheless we must use the real size here. */ - bs->total_sectors = be64_to_cpu(footer->size) / 512; + bs->total_sectors = be64_to_cpu(footer->size) / VHD_SECTOR_SIZE; /* Allow a maximum disk size of approximately 2 TB */ if (bs->total_sectors >= 65535LL * 255 * 255) { @@ -241,7 +255,7 @@ static int vpc_open(BlockDriverState *bs, int flags) for (i = 0; i < s->max_table_entries; i++) { be32_to_cpus(&s->pagetable[i]); - if (s->pagetable[i] != 0xFFFFFFFF) { + if (s->pagetable[i] != VHD_NO_PAGE) { int64_t next = (512 * (int64_t) s->pagetable[i]) + s->bitmap_size + s->block_size; @@ -290,7 +304,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs, int64_t sector_num, int write) { BDRVVPCState *s = bs->opaque; - uint64_t offset = sector_num * 512; + uint64_t offset = sector_num * VHD_SECTOR_SIZE; uint64_t bitmap_offset, block_offset; uint32_t pagetable_index, pageentry_index; @@ -298,7 +312,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs, pageentry_index = (offset % s->block_size) / 512; if (pagetable_index >= s->max_table_entries || - s->pagetable[pagetable_index] == 0xffffffff) { + s->pagetable[pagetable_index] == VHD_NO_PAGE) { return -1; // not allocated } @@ -392,8 +406,8 @@ static int64_t alloc_block(BlockDriverState *bs, int64_t sector_num) } // Write entry into in-memory BAT - index = (sector_num * 512) / s->block_size; - if (s->pagetable[index] != 0xFFFFFFFF) { + index = (sector_num * VHD_SECTOR_SIZE) / s->block_size; + if (s->pagetable[index] != VHD_NO_PAGE) { return -1; } @@ -451,18 +465,17 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num, } if (offset == -1) { - memset(buf, 0, sectors * BDRV_SECTOR_SIZE); + memset(buf, 0, sectors * VHD_SECTOR_SIZE); } else { - ret = bdrv_pread(bs->file, offset, buf, - sectors * BDRV_SECTOR_SIZE); - if (ret != sectors * BDRV_SECTOR_SIZE) { + ret = bdrv_pread(bs->file, offset, buf, sectors * VHD_SECTOR_SIZE); + if (ret < 0) { return -1; } } nb_sectors -= sectors; sector_num += sectors; - buf += sectors * BDRV_SECTOR_SIZE; + buf += sectors * VHD_SECTOR_SIZE; } return 0; } @@ -506,14 +519,14 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num, } } - ret = bdrv_pwrite(bs->file, offset, buf, sectors * BDRV_SECTOR_SIZE); - if (ret != sectors * BDRV_SECTOR_SIZE) { + ret = bdrv_pwrite(bs->file, offset, buf, sectors * VHD_SECTOR_SIZE); + if (ret < 0) { return -1; } nb_sectors -= sectors; sector_num += sectors; - buf += sectors * BDRV_SECTOR_SIZE; + buf += sectors * VHD_SECTOR_SIZE; } return 0; @@ -596,7 +609,7 @@ static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors) int ret = -EIO; // Write the footer (twice: at the beginning and at the end) - block_size = 0x200000; + block_size = VHD_DEFAULT_BLOCK_SIZE; num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512); if (write(fd, buf, FOOTER_SIZE) != FOOTER_SIZE) { @@ -627,11 +640,7 @@ static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors) memcpy(dyndisk_header->magic, "cxsparse", 8); - /* - * Note: The spec is actually wrong here for data_offset, it says - * 0xFFFFFFFF, but MS tools expect all 64 bits to be set. - */ - dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL); + dyndisk_header->data_offset = be64_to_cpu(VHD_NO_NEXT); dyndisk_header->table_offset = be64_to_cpu(3 * 512); dyndisk_header->version = be32_to_cpu(0x00010000); dyndisk_header->block_size = be32_to_cpu(block_size); @@ -717,7 +726,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) * sectors requested until we get enough (or fail). This ensures that * qemu-img convert doesn't truncate images, but rather rounds up. */ - total_sectors = total_size / BDRV_SECTOR_SIZE; + total_sectors = total_size / 512; if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl)) { ret = -EFBIG; goto fail; @@ -736,7 +745,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) if (disk_type == VHD_DYNAMIC) { footer->data_offset = be64_to_cpu(FOOTER_SIZE); } else { - footer->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL); + footer->data_offset = be64_to_cpu(VHD_NO_NEXT); } footer->timestamp = be32_to_cpu(time(NULL) - VHD_TIMESTAMP_BASE); @@ -745,7 +754,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) footer->minor = be16_to_cpu(0x0003); if (disk_type == VHD_DYNAMIC) { footer->orig_size = be64_to_cpu(total_sectors * 512); - footer->size = be64_to_cpu(total_sectors * 512); + footer->size = be64_to_cpu(total_sectors * VHD_SECTOR_SIZE); } else { footer->orig_size = be64_to_cpu(total_size); footer->size = be64_to_cpu(total_size); -- 1.7.10.4