Created
August 26, 2010 18:05
-
-
Save priteau/551876 to your computer and use it in GitHub Desktop.
Patch to xen-3.0.3-105.el5_5.5 SOURCES to fix QCOW images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/xen-blktap-qcow-empty.patch b/xen-blktap-qcow-empty.patch | |
| new file mode 100644 | |
| index 0000000..adf2026 | |
| --- /dev/null | |
| +++ b/xen-blktap-qcow-empty.patch | |
| @@ -0,0 +1,39 @@ | |
| +# HG changeset patch | |
| +# User Keir Fraser <[email protected]> | |
| +# Date 1244023910 -3600 | |
| +# Node ID c5fb6374e79fba152e149cdd55a5744d43762667 | |
| +# Parent f989778298d8074ad9135f3a538d449b6baab947 | |
| +blktap: fix empty QCOW images (bug 1430 part 2) | |
| + | |
| +Empty QCOW images consist of only the L1 table, this results in a | |
| +file size which is not sector-aligned. Since blktap uses O_DIRECT, the | |
| +block aligned read of the L1 table will go beyond the end of file and | |
| +thus returns the actual file size and not the expected length. | |
| +This patch checks whether at least the L1 table has been read. | |
| + | |
| +This should fix bug 1430. | |
| + | |
| +Signed-off-by: Andre Przywara <[email protected]> | |
| + | |
| +--- a/tools/blktap/drivers/block-qcow.c Wed Jun 03 11:11:04 2009 +0100 | |
| ++++ b/tools/blktap/drivers/block-qcow.c Wed Jun 03 11:11:50 2009 +0100 | |
| +@@ -824,7 +824,7 @@ static int tdqcow_open (struct disk_driv | |
| + l1_table_block = ROUNDUP(l1_table_block, 512); | |
| + ret = posix_memalign((void **)&buf2, 4096, l1_table_block); | |
| + if (ret != 0) goto fail; | |
| +- if (read(fd, buf2, l1_table_block) != l1_table_block) | |
| ++ if (read(fd, buf2, l1_table_block) < l1_table_size + s->l1_table_offset) | |
| + goto fail; | |
| + memcpy(s->l1_table, buf2 + s->l1_table_offset, l1_table_size); | |
| + | |
| +@@ -878,7 +878,8 @@ static int tdqcow_open (struct disk_driv | |
| + | |
| + memcpy(buf2 + s->l1_table_offset, s->l1_table, l1_table_size); | |
| + lseek(fd, 0, SEEK_SET); | |
| +- if (write(fd, buf2, l1_table_block) != l1_table_block) { | |
| ++ if (write(fd, buf2, l1_table_block) < | |
| ++ l1_table_size + s->l1_table_offset) { | |
| + DPRINTF("qcow: Failed to write new L1 table\n"); | |
| + goto fail; | |
| + } | |
| + | |
| diff --git a/xen-blktap-qcow-fix-roundup-usage.patch b/xen-blktap-qcow-fix-roundup-usage.patch | |
| new file mode 100644 | |
| index 0000000..83789c5 | |
| --- /dev/null | |
| +++ b/xen-blktap-qcow-fix-roundup-usage.patch | |
| @@ -0,0 +1,20 @@ | |
| +--- a/tools/blktap/drivers/block-qcow.c | |
| ++++ b/tools/blktap/drivers/block-qcow.c | |
| +@@ -920,7 +920,7 @@ int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) | |
| + | |
| + /* read the level 1 table */ | |
| + shift = s->cluster_bits + s->l2_bits; | |
| +- s->l1_size = ROUNDUP(header->size, 1LL << shift); | |
| ++ s->l1_size = ROUNDUP(header->size, 1LL << shift) >> shift; | |
| + | |
| + s->l1_table_offset = header->l1_table_offset; | |
| + | |
| +@@ -1355,7 +1355,7 @@ int qcow_create(const char *filename, uint64_t total_size, | |
| + } | |
| + | |
| + shift = header.cluster_bits + header.l2_bits; | |
| +- l1_size = ROUNDUP(size * 512, 1LL << shift); | |
| ++ l1_size = ROUNDUP(size * 512, 1LL << shift) >> shift; | |
| + | |
| + header.l1_table_offset = cpu_to_be64(header_size); | |
| + DPRINTF("L1 Table offset: %d, size %d\n", | |
| diff --git a/xen-blktap-qcow-handle-backing-files-correctly.patch b/xen-blktap-qcow-handle-backing-files-correctly.patch | |
| new file mode 100644 | |
| index 0000000..4f67e61 | |
| --- /dev/null | |
| +++ b/xen-blktap-qcow-handle-backing-files-correctly.patch | |
| @@ -0,0 +1,54 @@ | |
| +# HG changeset patch | |
| +# User Keir Fraser <[email protected]> | |
| +# Date 1224511704 -3600 | |
| +# Node ID 0a09de68c54153243d9293c82cbb6ddca4e4a76d | |
| +# Parent cbc254c59dd06f1f4197461bc51ca8dbcdf5b3af | |
| +blktap: Handle qcow backing files correctly. | |
| + | |
| +Signed-off-by: Stefano Stabellini <[email protected]> | |
| + | |
| +--- a/tools/blktap/drivers/block-qcow.c Mon Oct 20 15:05:48 2008 +0100 | |
| ++++ b/tools/blktap/drivers/block-qcow.c Mon Oct 20 15:08:24 2008 +0100 | |
| +@@ -734,8 +734,8 @@ static int tdqcow_open (struct disk_driv | |
| + | |
| + DPRINTF("QCOW: Opening %s\n",name); | |
| + | |
| +- o_flags = O_DIRECT | O_LARGEFILE | | |
| +- ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); | |
| ++ /* Since we don't handle O_DIRECT correctly, don't use it */ | |
| ++ o_flags = O_LARGEFILE | ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); | |
| + fd = open(name, o_flags); | |
| + if (fd < 0) { | |
| + DPRINTF("Unable to open %s (%d)\n",name,0 - errno); | |
| +@@ -1385,7 +1385,7 @@ static int tdqcow_get_parent_id(struct d | |
| + filename[len] = '\0'; | |
| + | |
| + id->name = strdup(filename); | |
| +- id->drivertype = DISK_TYPE_QCOW; | |
| ++ id->drivertype = DISK_TYPE_AIO; | |
| + err = 0; | |
| + out: | |
| + free(buf); | |
| +@@ -1397,17 +1397,15 @@ static int tdqcow_validate_parent(struct | |
| + { | |
| + struct stat stats; | |
| + uint64_t psize, csize; | |
| +- struct tdqcow_state *c = (struct tdqcow_state *)child->private; | |
| +- struct tdqcow_state *p = (struct tdqcow_state *)parent->private; | |
| +- | |
| +- if (stat(p->name, &stats)) | |
| ++ | |
| ++ if (stat(parent->name, &stats)) | |
| + return -EINVAL; | |
| +- if (get_filesize(p->name, &psize, &stats)) | |
| ++ if (get_filesize(parent->name, &psize, &stats)) | |
| + return -EINVAL; | |
| + | |
| +- if (stat(c->name, &stats)) | |
| ++ if (stat(child->name, &stats)) | |
| + return -EINVAL; | |
| +- if (get_filesize(c->name, &csize, &stats)) | |
| ++ if (get_filesize(child->name, &csize, &stats)) | |
| + return -EINVAL; | |
| + | |
| + if (csize != psize) | |
| diff --git a/xen-blktap-qcow-handling.patch b/xen-blktap-qcow-handling.patch | |
| new file mode 100644 | |
| index 0000000..d335ec1 | |
| --- /dev/null | |
| +++ b/xen-blktap-qcow-handling.patch | |
| @@ -0,0 +1,74 @@ | |
| +# HG changeset patch | |
| +# User Keir Fraser <[email protected]> | |
| +# Date 1272973099 -3600 | |
| +# Node ID d6cf080505cda4944e923194bd24faacece668d4 | |
| +# Parent 67303cccfb79206efd2975f9121807c95c05aa40 | |
| +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 <[email protected]> | |
| +Signed-off-by: Keir Fraser <[email protected]> | |
| + | |
| +--- a/tools/blktap/drivers/block-qcow.c Tue May 04 12:36:30 2010 +0100 | |
| ++++ b/tools/blktap/drivers/block-qcow.c Tue May 04 12:38:19 2010 +0100 | |
| +@@ -862,17 +862,23 @@ static int tdqcow_open (struct disk_driv | |
| + 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 | |
| + currently in memory. Then swap it back to native endianess | |
| + 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"); | |
| + | |
| +@@ -888,13 +894,6 @@ static int tdqcow_open (struct disk_driv | |
| + 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_driv | |
| + 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, ui | |
| + } else | |
| + flags = SPARSE_FILE; | |
| + | |
| ++ flags |= EXTHDR_L1_BIG_ENDIAN; | |
| + exthdr.flags = cpu_to_be32(flags); | |
| + | |
| + /* write all the data */ | |
| + | |
| diff --git a/xen-blktap-qcow-odirect.patch b/xen-blktap-qcow-odirect.patch | |
| new file mode 100644 | |
| index 0000000..60dd26c | |
| --- /dev/null | |
| +++ b/xen-blktap-qcow-odirect.patch | |
| @@ -0,0 +1,77 @@ | |
| +# HG changeset patch | |
| +# User Keir Fraser <[email protected]> | |
| +# Date 1224672933 -3600 | |
| +# Node ID 008505c3c65a76917bbd40ba7c2619cbd2fbca53 | |
| +# Parent 0978bdc056c88144553c2d441611545eced7bc4d | |
| +blktap: re-enable O_DIRECT in block_qcow.c | |
| + | |
| +Turns out that only two reads and writes in block-qcow.c need to be | |
| +fixed to work correctly with O_DIRECT. | |
| + | |
| +Signed-off-by: Stefano Stabellini <[email protected]> | |
| + | |
| +--- a/tools/blktap/drivers/block-qcow.c Wed Oct 22 11:53:51 2008 +0100 | |
| ++++ b/tools/blktap/drivers/block-qcow.c Wed Oct 22 11:55:33 2008 +0100 | |
| +@@ -722,10 +722,10 @@ static inline void init_fds(struct disk_ | |
| + /* Open the disk file and initialize qcow state. */ | |
| + static int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) | |
| + { | |
| +- int fd, len, i, shift, ret, size, l1_table_size, o_flags; | |
| ++ int fd, len, i, shift, ret, size, l1_table_size, o_flags, l1_table_block; | |
| + struct td_state *bs = dd->td_state; | |
| + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; | |
| +- char *buf; | |
| ++ char *buf, *buf2; | |
| + QCowHeader *header; | |
| + QCowHeader_ext *exthdr; | |
| + uint32_t cksum; | |
| +@@ -734,8 +734,8 @@ static int tdqcow_open (struct disk_driv | |
| + | |
| + DPRINTF("QCOW: Opening %s\n",name); | |
| + | |
| +- /* Since we don't handle O_DIRECT correctly, don't use it */ | |
| +- o_flags = O_LARGEFILE | ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); | |
| ++ o_flags = O_DIRECT | O_LARGEFILE | | |
| ++ ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); | |
| + fd = open(name, o_flags); | |
| + if (fd < 0) { | |
| + DPRINTF("Unable to open %s (%d)\n",name,0 - errno); | |
| +@@ -819,9 +819,14 @@ static int tdqcow_open (struct disk_driv | |
| + (int) (s->l1_size * sizeof(uint64_t)), | |
| + l1_table_size); | |
| + | |
| +- lseek(fd, s->l1_table_offset, SEEK_SET); | |
| +- if (read(fd, s->l1_table, l1_table_size) != l1_table_size) | |
| ++ lseek(fd, 0, SEEK_SET); | |
| ++ l1_table_block = l1_table_size + s->l1_table_offset; | |
| ++ l1_table_block = l1_table_block + 512 - (l1_table_block % 512); | |
| ++ ret = posix_memalign((void **)&buf2, 4096, l1_table_block); | |
| ++ if (ret != 0) goto fail; | |
| ++ if (read(fd, buf2, l1_table_block) != l1_table_block) | |
| + goto fail; | |
| ++ memcpy(s->l1_table, buf2 + s->l1_table_offset, l1_table_size); | |
| + | |
| + for(i = 0; i < s->l1_size; i++) { | |
| + be64_to_cpus(&s->l1_table[i]); | |
| +@@ -871,8 +876,9 @@ static int tdqcow_open (struct disk_driv | |
| + | |
| + 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) { | |
| ++ memcpy(buf2 + s->l1_table_offset, s->l1_table, l1_table_size); | |
| ++ lseek(fd, 0, SEEK_SET); | |
| ++ if (write(fd, buf2, l1_table_block) != l1_table_block) { | |
| + DPRINTF("qcow: Failed to write new L1 table\n"); | |
| + goto fail; | |
| + } | |
| +@@ -917,7 +923,7 @@ static int tdqcow_open (struct disk_driv | |
| + init_fds(dd); | |
| + | |
| + if (!final_cluster) | |
| +- s->fd_end = s->l1_table_offset + l1_table_size; | |
| ++ s->fd_end = l1_table_block; | |
| + else { | |
| + s->fd_end = lseek(fd, 0, SEEK_END); | |
| + if (s->fd_end == (off_t)-1) | |
| + | |
| diff --git a/xen-blktap-qcow-roundup.patch b/xen-blktap-qcow-roundup.patch | |
| new file mode 100644 | |
| index 0000000..e9771d0 | |
| --- /dev/null | |
| +++ b/xen-blktap-qcow-roundup.patch | |
| @@ -0,0 +1,66 @@ | |
| +# HG changeset patch | |
| +# User Keir Fraser <[email protected]> | |
| +# Date 1244023864 -3600 | |
| +# Node ID f989778298d8074ad9135f3a538d449b6baab947 | |
| +# Parent e7b63b30ae3da2c3184dfa6fc00a816f90a158d5 | |
| +blktap: fix and use ROUNDUP macro (bug 1430 part 1) | |
| + | |
| +As pointed out in Xen Bugzilla 1430 in the blktap QCOW driver the | |
| +rounding function is wrong in line 824 of block-qcow.c. | |
| +This patch replaces this (and other roundings) with the already | |
| +existing ROUNDUP macro (and fixes the usual macro pitfall). | |
| + | |
| +Signed-off-by: Andre Przywara <[email protected]> | |
| + | |
| +--- a/tools/blktap/drivers/block-qcow.c Wed Jun 03 11:10:07 2009 +0100 | |
| ++++ b/tools/blktap/drivers/block-qcow.c Wed Jun 03 11:11:04 2009 +0100 | |
| +@@ -55,7 +55,7 @@ | |
| + #define ROUNDUP(l, s) \ | |
| + ({ \ | |
| + (uint64_t)( \ | |
| +- (l + (s - 1)) - ((l + (s - 1)) % s)); \ | |
| ++ ((l) + ((s) - 1)) - (((l) + ((s) - 1)) % (s))); \ | |
| + }) | |
| + | |
| + #undef IOCB_IDX | |
| +@@ -800,14 +800,14 @@ static int tdqcow_open (struct disk_driv | |
| + | |
| + /* read the level 1 table */ | |
| + shift = s->cluster_bits + s->l2_bits; | |
| +- s->l1_size = (header->size + (1LL << shift) - 1) >> shift; | |
| ++ s->l1_size = ROUNDUP(header->size, 1LL << shift); | |
| + | |
| + s->l1_table_offset = header->l1_table_offset; | |
| + | |
| + /*allocate a 4Kbyte multiple of memory*/ | |
| + l1_table_size = s->l1_size * sizeof(uint64_t); | |
| + if (l1_table_size % 4096 > 0) { | |
| +- l1_table_size = ((l1_table_size >> 12) + 1) << 12; | |
| ++ l1_table_size = ROUNDUP(l1_table_size, 4096); | |
| + } | |
| + ret = posix_memalign((void **)&s->l1_table, 4096, l1_table_size); | |
| + if (ret != 0) goto fail; | |
| +@@ -821,7 +821,7 @@ static int tdqcow_open (struct disk_driv | |
| + | |
| + lseek(fd, 0, SEEK_SET); | |
| + l1_table_block = l1_table_size + s->l1_table_offset; | |
| +- l1_table_block = l1_table_block + 512 - (l1_table_block % 512); | |
| ++ l1_table_block = ROUNDUP(l1_table_block, 512); | |
| + ret = posix_memalign((void **)&buf2, 4096, l1_table_block); | |
| + if (ret != 0) goto fail; | |
| + if (read(fd, buf2, l1_table_block) != l1_table_block) | |
| +@@ -1226,11 +1226,11 @@ int qcow_create(const char *filename, ui | |
| + | |
| + header_size = (header_size + 7) & ~7; | |
| + if (header_size % 4096 > 0) { | |
| +- header_size = ((header_size >> 12) + 1) << 12; | |
| ++ header_size = ROUNDUP(header_size, 4096); | |
| + } | |
| + | |
| + shift = header.cluster_bits + header.l2_bits; | |
| +- l1_size = ((size * 512) + (1LL << shift) - 1) >> shift; | |
| ++ l1_size = ROUNDUP(size * 512, 1LL << shift); | |
| + | |
| + header.l1_table_offset = cpu_to_be64(header_size); | |
| + DPRINTF("L1 Table offset: %d, size %d\n", | |
| + |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment