aboutsummaryrefslogtreecommitdiffstats
path: root/tools/blktap
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-04 12:38:19 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-04 12:38:19 +0100
commit82fa47405a5f7b5071603e4df7387297303b6035 (patch)
treee849b2cce875a8158fb8c520ecca2ce813902887 /tools/blktap
parent15fb9e3a4e7de1344e596fd46e31fae9656fe5a4 (diff)
downloadxen-82fa47405a5f7b5071603e4df7387297303b6035.tar.gz
xen-82fa47405a5f7b5071603e4df7387297303b6035.tar.bz2
xen-82fa47405a5f7b5071603e4df7387297303b6035.zip
blktap: Fix old QCow tapdisk image handling
When I tried to use QCow image, I found that only each second boot is successful. As I discovered, this is caused by wrong handling old qcow tapdisk images. Extended header flag is not stored correctly so the blktap tries to change endian fo L1 table on each startup. From: Miroslav Rezanina <mrezanin@redhat.com> Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'tools/blktap')
-rw-r--r--tools/blktap/drivers/block-qcow.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c
index 8027fcaca2..0e4e9cfe0a 100644
--- a/tools/blktap/drivers/block-qcow.c
+++ b/tools/blktap/drivers/block-qcow.c
@@ -862,11 +862,12 @@ static int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flag
be32_to_cpus(&exthdr->xmagic);
if(exthdr->xmagic != XEN_MAGIC)
goto end_xenhdr;
-
+
+ be32_to_cpus(&exthdr->flags);
/* 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 ((exthdr->flags & EXTHDR_L1_BIG_ENDIAN) == 0) {
-
+ QCowHeader_ext *tmphdr = (QCowHeader_ext *)(buf2 + sizeof(QCowHeader));
/*
The image is broken. Fix it. The L1 table has already been
byte-swapped, so we can write it to the image file as it is
@@ -874,6 +875,11 @@ static int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flag
for operation.
*/
+ /* Change ENDIAN flag and copy it to store buffer */
+ exthdr->flags |= EXTHDR_L1_BIG_ENDIAN;
+ tmphdr->flags = cpu_to_be32(exthdr->flags);
+
+
DPRINTF("qcow: Converting image to big endian L1 table\n");
memcpy(buf2 + s->l1_table_offset, s->l1_table, l1_table_size);
@@ -888,13 +894,6 @@ static int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flag
cpu_to_be64s(&s->l1_table[i]);
}
- /* Write the big endian flag to the extended header */
- exthdr->flags |= EXTHDR_L1_BIG_ENDIAN;
-
- if (write(fd, buf, 512) != 512) {
- DPRINTF("qcow: Failed to write extended header\n");
- goto fail;
- }
}
/*Finally check the L1 table cksum*/
@@ -905,7 +904,6 @@ static int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flag
goto end_xenhdr;
be32_to_cpus(&exthdr->min_cluster_alloc);
- be32_to_cpus(&exthdr->flags);
s->sparse = (exthdr->flags & SPARSE_FILE);
s->min_cluster_alloc = exthdr->min_cluster_alloc;
}
@@ -1263,6 +1261,7 @@ int qcow_create(const char *filename, uint64_t total_size,
} else
flags = SPARSE_FILE;
+ flags |= EXTHDR_L1_BIG_ENDIAN;
exthdr.flags = cpu_to_be32(flags);
/* write all the data */