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 | } | ... | ... |