Commit 6e9ea0c0629fe25723494a19498bedf4b781cbfa
1 parent
29463b24
block-vpc: Don't silently create smaller image than requested
The algorithm from the VHD specification for CHS calculation silently limits images to 127 GB which may confuse a user who requested a larger image. Better output an error message and abort. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7109 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
12 additions
and
3 deletions
block-vpc.c
... | ... | @@ -433,14 +433,16 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num, |
433 | 433 | * |
434 | 434 | * Note that the geometry doesn't always exactly match total_sectors but |
435 | 435 | * may round it down. |
436 | + * | |
437 | + * Returns 0 on success, -EFBIG if the size is larger than 127 GB | |
436 | 438 | */ |
437 | -static void calculate_geometry(int64_t total_sectors, uint16_t* cyls, | |
439 | +static int calculate_geometry(int64_t total_sectors, uint16_t* cyls, | |
438 | 440 | uint8_t* heads, uint8_t* secs_per_cyl) |
439 | 441 | { |
440 | 442 | uint32_t cyls_times_heads; |
441 | 443 | |
442 | 444 | if (total_sectors > 65535 * 16 * 255) |
443 | - total_sectors = 65535 * 16 * 255; | |
445 | + return -EFBIG; | |
444 | 446 | |
445 | 447 | if (total_sectors > 65535 * 16 * 63) { |
446 | 448 | *secs_per_cyl = 255; |
... | ... | @@ -470,6 +472,8 @@ static void calculate_geometry(int64_t total_sectors, uint16_t* cyls, |
470 | 472 | // Note: Rounding up deviates from the Virtual PC behaviour |
471 | 473 | // However, we need this to avoid truncating images in qemu-img convert |
472 | 474 | *cyls = (cyls_times_heads + *heads - 1) / *heads; |
475 | + | |
476 | + return 0; | |
473 | 477 | } |
474 | 478 | |
475 | 479 | static int vpc_create(const char *filename, int64_t total_sectors, |
... | ... | @@ -493,7 +497,8 @@ static int vpc_create(const char *filename, int64_t total_sectors, |
493 | 497 | return -EIO; |
494 | 498 | |
495 | 499 | // Calculate matching total_size and geometry |
496 | - calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl); | |
500 | + if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl)) | |
501 | + return -EFBIG; | |
497 | 502 | total_sectors = (int64_t) cyls * heads * secs_per_cyl; |
498 | 503 | |
499 | 504 | // Prepare the Hard Disk Footer | ... | ... |
qemu-img.c
... | ... | @@ -306,6 +306,8 @@ static int img_create(int argc, char **argv) |
306 | 306 | if (ret < 0) { |
307 | 307 | if (ret == -ENOTSUP) { |
308 | 308 | error("Formatting or formatting option not supported for file format '%s'", fmt); |
309 | + } else if (ret == -EFBIG) { | |
310 | + error("The image size is too large for file format '%s'", fmt); | |
309 | 311 | } else { |
310 | 312 | error("Error while formatting"); |
311 | 313 | } |
... | ... | @@ -494,6 +496,8 @@ static int img_convert(int argc, char **argv) |
494 | 496 | if (ret < 0) { |
495 | 497 | if (ret == -ENOTSUP) { |
496 | 498 | error("Formatting not supported for file format '%s'", out_fmt); |
499 | + } else if (ret == -EFBIG) { | |
500 | + error("The image size is too large for file format '%s'", out_fmt); | |
497 | 501 | } else { |
498 | 502 | error("Error while formatting '%s'", out_filename); |
499 | 503 | } | ... | ... |