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,14 +433,16 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num, | ||
| 433 | * | 433 | * |
| 434 | * Note that the geometry doesn't always exactly match total_sectors but | 434 | * Note that the geometry doesn't always exactly match total_sectors but |
| 435 | * may round it down. | 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 | uint8_t* heads, uint8_t* secs_per_cyl) | 440 | uint8_t* heads, uint8_t* secs_per_cyl) |
| 439 | { | 441 | { |
| 440 | uint32_t cyls_times_heads; | 442 | uint32_t cyls_times_heads; |
| 441 | 443 | ||
| 442 | if (total_sectors > 65535 * 16 * 255) | 444 | if (total_sectors > 65535 * 16 * 255) |
| 443 | - total_sectors = 65535 * 16 * 255; | 445 | + return -EFBIG; |
| 444 | 446 | ||
| 445 | if (total_sectors > 65535 * 16 * 63) { | 447 | if (total_sectors > 65535 * 16 * 63) { |
| 446 | *secs_per_cyl = 255; | 448 | *secs_per_cyl = 255; |
| @@ -470,6 +472,8 @@ static void calculate_geometry(int64_t total_sectors, uint16_t* cyls, | @@ -470,6 +472,8 @@ static void calculate_geometry(int64_t total_sectors, uint16_t* cyls, | ||
| 470 | // Note: Rounding up deviates from the Virtual PC behaviour | 472 | // Note: Rounding up deviates from the Virtual PC behaviour |
| 471 | // However, we need this to avoid truncating images in qemu-img convert | 473 | // However, we need this to avoid truncating images in qemu-img convert |
| 472 | *cyls = (cyls_times_heads + *heads - 1) / *heads; | 474 | *cyls = (cyls_times_heads + *heads - 1) / *heads; |
| 475 | + | ||
| 476 | + return 0; | ||
| 473 | } | 477 | } |
| 474 | 478 | ||
| 475 | static int vpc_create(const char *filename, int64_t total_sectors, | 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,7 +497,8 @@ static int vpc_create(const char *filename, int64_t total_sectors, | ||
| 493 | return -EIO; | 497 | return -EIO; |
| 494 | 498 | ||
| 495 | // Calculate matching total_size and geometry | 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 | total_sectors = (int64_t) cyls * heads * secs_per_cyl; | 502 | total_sectors = (int64_t) cyls * heads * secs_per_cyl; |
| 498 | 503 | ||
| 499 | // Prepare the Hard Disk Footer | 504 | // Prepare the Hard Disk Footer |
qemu-img.c
| @@ -306,6 +306,8 @@ static int img_create(int argc, char **argv) | @@ -306,6 +306,8 @@ static int img_create(int argc, char **argv) | ||
| 306 | if (ret < 0) { | 306 | if (ret < 0) { |
| 307 | if (ret == -ENOTSUP) { | 307 | if (ret == -ENOTSUP) { |
| 308 | error("Formatting or formatting option not supported for file format '%s'", fmt); | 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 | } else { | 311 | } else { |
| 310 | error("Error while formatting"); | 312 | error("Error while formatting"); |
| 311 | } | 313 | } |
| @@ -494,6 +496,8 @@ static int img_convert(int argc, char **argv) | @@ -494,6 +496,8 @@ static int img_convert(int argc, char **argv) | ||
| 494 | if (ret < 0) { | 496 | if (ret < 0) { |
| 495 | if (ret == -ENOTSUP) { | 497 | if (ret == -ENOTSUP) { |
| 496 | error("Formatting not supported for file format '%s'", out_fmt); | 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 | } else { | 501 | } else { |
| 498 | error("Error while formatting '%s'", out_filename); | 502 | error("Error while formatting '%s'", out_filename); |
| 499 | } | 503 | } |