[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] tapdisk: Fix L1 table endianess of qcow images
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1206638017 0 # Node ID 17e30b91b9e2a6607d7b2a7db011ac2a4f11d1d1 # Parent a819cf758b8cf5624214ba59bc0c13172b3c7f05 tapdisk: Fix L1 table endianess of qcow images Fix tapdisk to use big endian L1 tables as used by qemu/ioemu. Old tapdisk images with native endianess are automagically converted to big endian when the image file is opened for the first time. Signed-off-by: Kevin Wolf <kwolf@xxxxxxx> --- tools/blktap/drivers/block-qcow.c | 68 ++++++++++++++++++++++++++++++++------ 1 files changed, 59 insertions(+), 9 deletions(-) diff -r a819cf758b8c -r 17e30b91b9e2 tools/blktap/drivers/block-qcow.c --- a/tools/blktap/drivers/block-qcow.c Thu Mar 27 16:20:25 2008 +0000 +++ b/tools/blktap/drivers/block-qcow.c Thu Mar 27 17:13:37 2008 +0000 @@ -76,6 +76,7 @@ #define QCOW_OFLAG_COMPRESSED (1LL << 63) #define SPARSE_FILE 0x01 +#define EXTHDR_L1_BIG_ENDIAN 0x02 #ifndef O_BINARY #define O_BINARY 0 @@ -147,19 +148,30 @@ static int decompress_cluster(struct tdq static uint32_t gen_cksum(char *ptr, int len) { + int i; unsigned char *md; uint32_t ret; md = malloc(MD5_DIGEST_LENGTH); if(!md) return 0; - - if (MD5((unsigned char *)ptr, len, md) != md) { - free(md); - return 0; - } - - memcpy(&ret, md, sizeof(uint32_t)); + + /* Convert L1 table to big endian */ + for(i = 0; i < len / sizeof(uint64_t); i++) { + cpu_to_be64s(&((uint64_t*) ptr)[i]); + } + + /* Generate checksum */ + if (MD5((unsigned char *)ptr, len, md) != md) + ret = 0; + else + memcpy(&ret, md, sizeof(uint32_t)); + + /* Convert L1 table back to native endianess */ + for(i = 0; i < len / sizeof(uint64_t); i++) { + be64_to_cpus(&((uint64_t*) ptr)[i]); + } + free(md); return ret; } @@ -354,7 +366,8 @@ static uint64_t get_cluster_offset(struc int n_start, int n_end) { int min_index, i, j, l1_index, l2_index, l2_sector, l1_sector; - char *tmp_ptr, *tmp_ptr2, *l2_ptr, *l1_ptr; + char *tmp_ptr2, *l2_ptr, *l1_ptr; + uint64_t *tmp_ptr; uint64_t l2_offset, *l2_table, cluster_offset, tmp; uint32_t min_count; int new_l2_table; @@ -400,6 +413,11 @@ static uint64_t get_cluster_offset(struc DPRINTF("ERROR allocating memory for L1 table\n"); } memcpy(tmp_ptr, l1_ptr, 4096); + + /* Convert block to write to big endian */ + for(i = 0; i < 4096 / sizeof(uint64_t); i++) { + cpu_to_be64s(&tmp_ptr[i]); + } /* * Issue non-asynchronous L1 write. @@ -777,7 +795,7 @@ int tdqcow_open (struct disk_driver *dd, goto fail; for(i = 0; i < s->l1_size; i++) { - //be64_to_cpus(&s->l1_table[i]); + be64_to_cpus(&s->l1_table[i]); //DPRINTF("L1[%d] => %llu\n", i, s->l1_table[i]); if (s->l1_table[i] > final_cluster) final_cluster = s->l1_table[i]; @@ -810,6 +828,38 @@ int tdqcow_open (struct disk_driver *dd, be32_to_cpus(&exthdr->xmagic); if(exthdr->xmagic != XEN_MAGIC) goto end_xenhdr; + + /* 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) { + + /* + 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 + currently in memory. Then swap it back to native endianess + for operation. + */ + + DPRINTF("qcow: Converting image to big endian L1 table\n"); + + lseek(fd, s->l1_table_offset, SEEK_SET); + if (write(fd, s->l1_table, l1_table_size) != l1_table_size) { + DPRINTF("qcow: Failed to write new L1 table\n"); + goto fail; + } + + for(i = 0;i < s->l1_size; i++) { + 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*/ be32_to_cpus(&exthdr->cksum); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |