Index: qemu/block-qcow2.c =================================================================== --- qemu.orig/block-qcow2.c 2008-06-19 14:38:59.000000000 +0200 +++ qemu/block-qcow2.c 2008-06-20 14:23:35.000000000 +0200 @@ -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,