All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@suse.de>
To: Otavio Salvador <otavio@ossystems.com.br>
Cc: xen-devel@lists.xensource.com, Keir Fraser <keir.fraser@eu.citrix.com>
Subject: Re: The two image formats called qcow
Date: Wed, 26 Mar 2008 14:54:38 +0100	[thread overview]
Message-ID: <47EA559E.6000309@suse.de> (raw)
In-Reply-To: <87ej9xeix3.fsf@ossystems.com.br>

[-- Attachment #1: Type: text/plain, Size: 2004 bytes --]

Otavio Salvador schrieb:
> Kevin Wolf <kwolf@suse.de> writes:
> 
>> Is it an option to convert broken images to big endian when it is opened
>> for the first time in ioemu? In this case, the fix for older versions
>> could be in one place at least instead of being scattered over the whole
>> file. Then you wouldn't be able to open such a file with tapdisk again,
>> though.
> 
> If it could be done, a note in release notes would be required to warn
> users that when it has been opened in a newer version using ioemu it
> wouldn't be possible to be used again by tap driver anymore.

I agree, a note wouldn't be wrong.

> But yes, this would be an easy to use option if it's not too messy and
> takes too long to convert the image (otherwise user can think that the
> system has freeze).

Converting the image means byte-swapping the L1 table which is some
kilobytes in size. This is done in no time, the user won't even notice
the delay. The attached patch implements this conversion.

What should we do with the tapdisk implementation? Leave it broken and
hope that it will disappear soon, add support for big endian L1 tables
or do a conversion the other way round? The latter doesn't feel right
(in fact it would be intentionally breaking a correct image), but adding
support for big endian is much more critical because we end up with
"mixed endian" if we miss one conversion...

Kevin


ioemu: Fix L1 table endianess of qcow images created by tapdisk

The qemu/ioemu implementation of the qcow format uses a big endian L1
table. tapdisk omits the necessary conversion, so qcow images have the
wrong endianess and cannot be read by correct implementations of qcow.

This patch detects broken tapdisk images and converts their L1 tables to
big endian when the image file is opened in ioemu for the first time.
The fixed image has a new flag EXTHDR_L1_BIG_ENDIAN set in the extended
header.

Note that a converted image cannot be opened by tapdisk again.

Signed-off-by: Kevin Wolf <kwolf@suse.de>

[-- Attachment #2: ioemu-qcow-fix-tapdisk-images.patch --]
[-- Type: text/x-patch, Size: 2506 bytes --]

diff -r 81147306041a tools/ioemu/block-qcow.c
--- a/tools/ioemu/block-qcow.c	Tue Mar 25 14:37:43 2008
+++ b/tools/ioemu/block-qcow.c	Wed Mar 26 15:25:37 2008
@@ -37,6 +37,11 @@
 
 #define QCOW_OFLAG_COMPRESSED (1LL << 63)
 
+#define XEN_MAGIC  (('X' << 24) | ('E' << 16) | ('N' << 8) | 0xfb)
+
+#define EXTHDR_SPARSE_FILE      0x01
+#define EXTHDR_L1_BIG_ENDIAN    0x02
+
 typedef struct QCowHeader {
     uint32_t magic;
     uint32_t version;
@@ -49,6 +54,14 @@
     uint32_t crypt_method;
     uint64_t l1_table_offset;
 } QCowHeader;
+
+/*Extended header for Xen enhancements*/
+typedef struct QCowHeader_ext {
+    uint32_t xmagic;
+    uint32_t cksum;
+    uint32_t min_cluster_alloc;
+    uint32_t flags;
+} QCowHeader_ext;
 
 #define L2_CACHE_SIZE 16
 
@@ -137,6 +150,51 @@
     if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
         s->l1_size * sizeof(uint64_t))
         goto fail;
+
+    /* Try to detect old tapdisk images. They have to be fixed because they
+     * don't use big endian but native endianess for the L1 table */
+	if (header.backing_file_offset == 0 && s->l1_table_offset % 4096 == 0) {
+	
+        QCowHeader_ext exthdr;
+        uint64_t l1_bytes = s->l1_size * sizeof(uint64_t);
+
+        if (bdrv_pread(s->hd, sizeof(header), &exthdr, sizeof(exthdr)) 
+                != sizeof(exthdr))
+            goto end_xenhdr;
+
+		be32_to_cpus(&exthdr.xmagic);
+		if (exthdr.xmagic != XEN_MAGIC) 
+			goto end_xenhdr;
+
+		be32_to_cpus(&exthdr.flags);
+        if (exthdr.flags & EXTHDR_L1_BIG_ENDIAN)
+            goto end_xenhdr;
+
+        /* The image is broken. Fix it. */
+        fprintf(stderr, "qcow: Converting image to big endian L1 table\n");
+
+        for(i = 0;i < s->l1_size; i++) {
+            cpu_to_be64s(&s->l1_table[i]);
+        }
+    
+        if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, 
+                l1_bytes) != l1_bytes) {
+            fprintf(stderr, "qcow: Failed to write new L1 table\n");
+            goto fail;
+        }
+
+        exthdr.flags |= EXTHDR_L1_BIG_ENDIAN;
+        cpu_to_be32s(&exthdr.flags);
+        
+        if (bdrv_pwrite(s->hd, sizeof(header), &exthdr, sizeof(exthdr)) 
+                != sizeof(exthdr)) {
+            fprintf(stderr, "qcow: Failed to write extended header\n");
+            goto fail;
+        }
+    }
+end_xenhdr:
+
+    /* L1 table is big endian now */
     for(i = 0;i < s->l1_size; i++) {
         be64_to_cpus(&s->l1_table[i]);
     }

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

  reply	other threads:[~2008-03-26 13:54 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-25 17:25 The two image formats called qcow Kevin Wolf
2008-03-25 18:58 ` Otavio Salvador
2008-03-26  8:10   ` Keir Fraser
2008-03-26  8:50     ` Kevin Wolf
2008-03-26 13:03       ` Otavio Salvador
2008-03-26 13:54         ` Kevin Wolf [this message]
2008-03-26 14:02           ` Keir Fraser
2008-03-26 14:07             ` Kevin Wolf
2008-03-26 14:15               ` Keir Fraser
2008-03-26 14:22                 ` Kevin Wolf
2008-03-27  9:55           ` [PATCH] tapdisk: Fix L1 table endianess of qcow images Kevin Wolf
2008-03-26 13:23       ` The two image formats called qcow Daniel P. Berrange

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47EA559E.6000309@suse.de \
    --to=kwolf@suse.de \
    --cc=keir.fraser@eu.citrix.com \
    --cc=otavio@ossystems.com.br \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.