Index: xen-3.3.1-testing/tools/ioemu-remote/block-qcow2.c
===================================================================
--- xen-3.3.1-testing.orig/tools/ioemu-remote/block-qcow2.c
+++ xen-3.3.1-testing/tools/ioemu-remote/block-qcow2.c
@@ -808,6 +808,8 @@ static void qcow_aio_read_cb(void *opaqu
     BlockDriverState *bs = acb->common.bs;
     BDRVQcowState *s = bs->opaque;
     int index_in_cluster, n1;
+    uint64_t next;
+    int n;
 
     acb->hd_aiocb = NULL;
     if (ret < 0) {
@@ -846,11 +848,22 @@ static void qcow_aio_read_cb(void *opaqu
     acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
                                              0, 0, 0, 0);
     index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
-    acb->n = s->cluster_sectors - index_in_cluster;
-    if (acb->n > acb->nb_sectors)
-        acb->n = acb->nb_sectors;
 
     if (!acb->cluster_offset) {
+        /* seek how many clusters we must read from the base image */
+        n = s->cluster_sectors;
+        while (n < acb->nb_sectors + index_in_cluster) {
+            next = get_cluster_offset(bs, (acb->sector_num + n) << 9,
+                                      0, 0, 0, 0);
+            if (next)
+                break;
+            n += s->cluster_sectors;
+        }
+        n -= index_in_cluster;
+        if (n > acb->nb_sectors)
+            n = acb->nb_sectors;
+        acb->n = n;
+
         if (bs->backing_hd) {
             /* read from the base image */
             n1 = backing_read1(bs->backing_hd, acb->sector_num,
@@ -869,6 +882,9 @@ static void qcow_aio_read_cb(void *opaqu
             goto redo;
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
+        acb->n = s->cluster_sectors - index_in_cluster;
+        if (acb->n > acb->nb_sectors)
+            acb->n = acb->nb_sectors;
         /* add AIO support for compressed blocks ? */
         if (decompress_cluster(s, acb->cluster_offset) < 0)
             goto fail;
@@ -880,6 +896,22 @@ static void qcow_aio_read_cb(void *opaqu
             ret = -EIO;
             goto fail;
         }
+
+        /* seek how many clusters we can read */
+
+        n = s->cluster_sectors;
+        while (n < acb->nb_sectors + index_in_cluster) {
+            next = get_cluster_offset(bs, (acb->sector_num + n) << 9,
+                                      0, 0, 0, 0);
+            if (next != acb->cluster_offset + (n << 9))
+                break;
+            n += s->cluster_sectors;
+        }
+        n -= index_in_cluster;
+        if (n > acb->nb_sectors)
+            n = acb->nb_sectors;
+        acb->n = n;
+
         acb->hd_aiocb = bdrv_aio_read(s->hd,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             acb->buf, acb->n, qcow_aio_read_cb, acb);
@@ -928,6 +960,9 @@ static void qcow_aio_write_cb(void *opaq
     int index_in_cluster;
     uint64_t cluster_offset;
     const uint8_t *src_buf;
+    uint64_t next;
+    int n;
+    int alloc;
 
     acb->hd_aiocb = NULL;
 
@@ -972,6 +1007,25 @@ static void qcow_aio_write_cb(void *opaq
                         acb->n, 1, &s->aes_encrypt_key);
         src_buf = acb->cluster_data;
     } else {
+
+        /* seek how many clusters we can write */
+
+        n = s->cluster_sectors;
+        while(n < acb->nb_sectors + index_in_cluster) {
+            alloc = s->cluster_sectors;
+            if (n + alloc > acb->nb_sectors + index_in_cluster)
+                alloc = acb->nb_sectors + index_in_cluster -  n;
+            next = get_cluster_offset(bs, (acb->sector_num + n) << 9,
+                                      1, 0, 0, alloc);
+            if (next != cluster_offset + (n << 9))
+                break;
+            n += alloc;
+        }
+        n -= index_in_cluster;
+        if (n > acb->nb_sectors)
+            n = acb->nb_sectors;
+        acb->n = n;
+
         src_buf = acb->buf;
     }
     acb->hd_aiocb = bdrv_aio_write(s->hd,