diff options
Diffstat (limited to 'block/vpc.c')
-rw-r--r-- | block/vpc.c | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/block/vpc.c b/block/vpc.c index b6bf52f..82229ef 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -23,9 +23,12 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#include "block_int.h" -#include "module.h" -#include "migration.h" +#include "block/block_int.h" +#include "qemu/module.h" +#include "migration/migration.h" +#if defined(CONFIG_UUID) +#include <uuid/uuid.h> +#endif /**************************************************************/ @@ -160,24 +163,33 @@ static int vpc_open(BlockDriverState *bs, int flags) struct vhd_dyndisk_header* dyndisk_header; uint8_t buf[HEADER_SIZE]; uint32_t checksum; - int err = -1; int disk_type = VHD_DYNAMIC; + int ret; - if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE) + ret = bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE); + if (ret < 0) { goto fail; + } footer = (struct vhd_footer*) s->footer_buf; if (strncmp(footer->creator, "conectix", 8)) { int64_t offset = bdrv_getlength(bs->file); - if (offset < HEADER_SIZE) { + if (offset < 0) { + ret = offset; + goto fail; + } else if (offset < HEADER_SIZE) { + ret = -EINVAL; goto fail; } + /* If a fixed disk, the footer is found only at the end of the file */ - if (bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, HEADER_SIZE) - != HEADER_SIZE) { + ret = bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, + HEADER_SIZE); + if (ret < 0) { goto fail; } if (strncmp(footer->creator, "conectix", 8)) { + ret = -EMEDIUMTYPE; goto fail; } disk_type = VHD_FIXED; @@ -198,20 +210,23 @@ static int vpc_open(BlockDriverState *bs, int flags) bs->total_sectors = (int64_t) be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl; - if (bs->total_sectors >= 65535 * 16 * 255) { - err = -EFBIG; + /* Allow a maximum disk size of approximately 2 TB */ + if (bs->total_sectors >= 65535LL * 255 * 255) { + ret = -EFBIG; goto fail; } if (disk_type == VHD_DYNAMIC) { - if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, - HEADER_SIZE) != HEADER_SIZE) { + ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, + HEADER_SIZE); + if (ret < 0) { goto fail; } dyndisk_header = (struct vhd_dyndisk_header *) buf; if (strncmp(dyndisk_header->magic, "cxsparse", 8)) { + ret = -EINVAL; goto fail; } @@ -222,8 +237,10 @@ static int vpc_open(BlockDriverState *bs, int flags) s->pagetable = g_malloc(s->max_table_entries * 4); s->bat_offset = be64_to_cpu(dyndisk_header->table_offset); - if (bdrv_pread(bs->file, s->bat_offset, s->pagetable, - s->max_table_entries * 4) != s->max_table_entries * 4) { + + ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable, + s->max_table_entries * 4); + if (ret < 0) { goto fail; } @@ -261,8 +278,13 @@ static int vpc_open(BlockDriverState *bs, int flags) migrate_add_blocker(s->migration_blocker); return 0; - fail: - return err; + +fail: + g_free(s->pagetable); +#ifdef CACHE + g_free(s->pageentry_u8); +#endif + return ret; } static int vpc_reopen_prepare(BDRVReopenState *state, @@ -524,19 +546,27 @@ static coroutine_fn int vpc_co_write(BlockDriverState *bs, int64_t sector_num, * Note that the geometry doesn't always exactly match total_sectors but * may round it down. * - * Returns 0 on success, -EFBIG if the size is larger than 127 GB + * Returns 0 on success, -EFBIG if the size is larger than ~2 TB. Override + * the hardware EIDE and ATA-2 limit of 16 heads (max disk size of 127 GB) + * and instead allow up to 255 heads. */ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, uint8_t* heads, uint8_t* secs_per_cyl) { uint32_t cyls_times_heads; - if (total_sectors > 65535 * 16 * 255) + /* Allow a maximum disk size of approximately 2 TB */ + if (total_sectors > 65535LL * 255 * 255) { return -EFBIG; + } if (total_sectors > 65535 * 16 * 63) { *secs_per_cyl = 255; - *heads = 16; + if (total_sectors > 65535 * 16 * 255) { + *heads = 255; + } else { + *heads = 16; + } cyls_times_heads = total_sectors / *secs_per_cyl; } else { *secs_per_cyl = 17; @@ -739,7 +769,9 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) footer->type = be32_to_cpu(disk_type); - /* TODO uuid is missing */ +#if defined(CONFIG_UUID) + uuid_generate(footer->uuid); +#endif footer->checksum = be32_to_cpu(vpc_checksum(buf, HEADER_SIZE)); |