diff mbox

[v2] qcow2: Store exact backing format length

Message ID 1259240622-13469-1-git-send-email-kwolf@redhat.com
State New
Headers show

Commit Message

Kevin Wolf Nov. 26, 2009, 1:03 p.m. UTC
Currently qcow2 unnecessarily rounds up the length of the backing format string
to the next multiple of 8. At the same time, the array in BlockDriverState can
only hold 15 characters, so in effect backing formats with 9 characters or more
don't work (e.g. host_device).

Save the real string length and things start to work for all valid image format
names.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---

v2:
- Don't rely on sizeof(ext) being a multiple of 8

 block/qcow2.c |   16 +++++++++-------
 1 files changed, 9 insertions(+), 7 deletions(-)

Comments

Markus Armbruster Dec. 1, 2009, 9:45 a.m. UTC | #1
Kevin Wolf <kwolf@redhat.com> writes:

> Currently qcow2 unnecessarily rounds up the length of the backing format string
> to the next multiple of 8. At the same time, the array in BlockDriverState can
> only hold 15 characters, so in effect backing formats with 9 characters or more
> don't work (e.g. host_device).
>
> Save the real string length and things start to work for all valid image format
> names.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Looks good to me.

> ---
>
> v2:
> - Don't rely on sizeof(ext) being a multiple of 8

Broken before your patch, so this is bonus fix.
diff mbox

Patch

diff --git a/block/qcow2.c b/block/qcow2.c
index 3954cf1..984264b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -124,12 +124,12 @@  static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
 #ifdef DEBUG_EXT
             printf("Qcow2: Got format extension %s\n", bs->backing_format);
 #endif
-            offset += ((ext.len + 7) & ~7);
+            offset = ((offset + ext.len + 7) & ~7);
             break;
 
         default:
             /* unknown magic -- just skip it */
-            offset += ((ext.len + 7) & ~7);
+            offset = ((offset + ext.len + 7) & ~7);
             break;
         }
     }
@@ -738,6 +738,7 @@  static int qcow_create2(const char *filename, int64_t total_size,
 
     int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
     int ref_clusters, backing_format_len = 0;
+    int rounded_ext_bf_len = 0;
     QCowHeader header;
     uint64_t tmp, offset;
     QCowCreateState s1, *s = &s1;
@@ -759,8 +760,9 @@  static int qcow_create2(const char *filename, int64_t total_size,
         if (backing_format) {
             ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT;
             backing_format_len = strlen(backing_format);
-            ext_bf.len = (backing_format_len + 7) & ~7;
-            header_size += ((sizeof(ext_bf) + ext_bf.len + 7) & ~7);
+            ext_bf.len = backing_format_len;
+            rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7;
+            header_size += rounded_ext_bf_len;
         }
         header.backing_file_offset = cpu_to_be64(header_size);
         backing_filename_len = strlen(backing_file);
@@ -828,15 +830,15 @@  static int qcow_create2(const char *filename, int64_t total_size,
     if (backing_file) {
         if (backing_format_len) {
             char zero[16];
-            int d = ext_bf.len - backing_format_len;
+            int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf));
 
             memset(zero, 0, sizeof(zero));
             cpu_to_be32s(&ext_bf.magic);
             cpu_to_be32s(&ext_bf.len);
             write(fd, &ext_bf, sizeof(ext_bf));
             write(fd, backing_format, backing_format_len);
-            if (d>0) {
-                write(fd, zero, d);
+            if (padding > 0) {
+                write(fd, zero, padding);
             }
         }
         write(fd, backing_file, backing_filename_len);