Skip to content

Instantly share code, notes, and snippets.

@priteau
Created August 26, 2010 18:05
Show Gist options
  • Select an option

  • Save priteau/551876 to your computer and use it in GitHub Desktop.

Select an option

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
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