From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:37015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TjARL-0007fG-BQ for qemu-devel@nongnu.org; Thu, 13 Dec 2012 10:11:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TjARD-0005tc-QT for qemu-devel@nongnu.org; Thu, 13 Dec 2012 10:11:11 -0500 Received: from mx1.redhat.com ([209.132.183.28]:37214) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TjARD-0005tE-H2 for qemu-devel@nongnu.org; Thu, 13 Dec 2012 10:11:03 -0500 From: Kevin Wolf Date: Thu, 13 Dec 2012 16:10:16 +0100 Message-Id: <1355411450-12761-10-git-send-email-kwolf@redhat.com> In-Reply-To: <1355411450-12761-1-git-send-email-kwolf@redhat.com> References: <1355411450-12761-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 09/43] block: vpc support for ~2 TB disks List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: anthony@codemonkey.ws Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Charles Arnold The VHD specification allows for up to a 2 TB disk size. The current implementation in qemu emulates EIDE and ATA-2 hardware which only allows for up to 127 GB. This disk size limitation can be overridden by allowing up to 255 heads instead of the normal 4 bit limitation of 16. Doing so allows disk images to be created of up to nearly 2 TB. This change does not violate the VHD format specification nor does it change how smaller disks (ie, <=127GB) are defined. [Charles Arnold also writes: "In analyzing a 160 GB VHD fixed disk image created on Windows 2008 R2, it appears that MS is also ignoring the CHS values in the footer geometry field in whatever driver they use for accessing the image. The CHS values are set at 65535,16,255 which obviously doesn't represent an image size of 160 GB." -- Stefan] Signed-off-by: Charles Arnold Reviewed-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- block/vpc.c | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index f14c6ae..566e9a3 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -201,7 +201,8 @@ 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) { + /* Allow a maximum disk size of approximately 2 TB */ + if (bs->total_sectors >= 65535LL * 255 * 255) { err = -EFBIG; goto fail; } @@ -527,19 +528,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; -- 1.7.6.5