aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Weil <weil@mail.berlios.de>2010-05-10 21:46:26 +0200
committerKevin Wolf <kwolf@redhat.com>2010-07-14 11:46:22 +0200
commit39187b5192bf16a6bbd3f272bef88f92e61b4c02 (patch)
tree69f9a0830c1794f3ce150215d5ed1f03a48316ef
parent729862401ddbf2554807f085e234e26625ba542c (diff)
block/vpc: Fix conversion from size to disk geometry
The VHD algorithm calculates a disk geometry which is usually smaller than the requested size. QEMU tried to round up but failed for certain sizes: qemu-img create -f vpc disk.vpc 9437184 would create an image with 9435136 bytes (which is too small for qemu-img convert). Instead of hacking the geometry algorithm, the patch increases the number of sectors until we get enough sectors. Cc: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Weil <weil@mail.berlios.de> Signed-off-by: Kevin Wolf <kwolf@redhat.com> (cherry picked from commit dede4188cc817a039154ed2ecd7f3285f6b94056)
-rw-r--r--block/vpc.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/block/vpc.c b/block/vpc.c
index 950ad58b3..afe6f1a9a 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -470,9 +470,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
}
}
- // Note: Rounding up deviates from the Virtual PC behaviour
- // However, we need this to avoid truncating images in qemu-img convert
- *cyls = (cyls_times_heads + *heads - 1) / *heads;
+ *cyls = cyls_times_heads / *heads;
return 0;
}
@@ -484,9 +482,9 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
struct vhd_dyndisk_header* dyndisk_header =
(struct vhd_dyndisk_header*) buf;
int fd, i;
- uint16_t cyls;
- uint8_t heads;
- uint8_t secs_per_cyl;
+ uint16_t cyls = 0;
+ uint8_t heads = 0;
+ uint8_t secs_per_cyl = 0;
size_t block_size, num_bat_entries;
int64_t total_sectors = 0;
@@ -503,9 +501,14 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
if (fd < 0)
return -EIO;
- // Calculate matching total_size and geometry
- if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl))
- return -EFBIG;
+ /* Calculate matching total_size and geometry. Increase the number of
+ sectors requested until we get enough (or fail). */
+ for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
+ if (calculate_geometry(total_sectors + i,
+ &cyls, &heads, &secs_per_cyl)) {
+ return -EFBIG;
+ }
+ }
total_sectors = (int64_t) cyls * heads * secs_per_cyl;
// Prepare the Hard Disk Footer