diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-08-06 13:34:04 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-08-06 13:34:04 +0000 |
commit | a946592212874f1e214e0db365c29e8de1179847 (patch) | |
tree | ef94d1666c46d81a5f35c3e57349d7e6f98da161 /block-qcow2.c | |
parent | 1aacf3489b67a907fa1b316a81e8991782f57199 (diff) |
handle read outside the backing file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2093 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'block-qcow2.c')
-rw-r--r-- | block-qcow2.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/block-qcow2.c b/block-qcow2.c index 7d92ca9620..bc2aa14bb2 100644 --- a/block-qcow2.c +++ b/block-qcow2.c @@ -696,11 +696,26 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) return 0; } +/* handle reading after the end of the backing file */ +static int backing_read1(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors) +{ + int n1; + if ((sector_num + nb_sectors) <= bs->total_sectors) + return nb_sectors; + if (sector_num >= bs->total_sectors) + n1 = 0; + else + n1 = bs->total_sectors - sector_num; + memset(buf + n1 * 512, 0, 512 * (nb_sectors - n1)); + return n1; +} + static int qcow_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { BDRVQcowState *s = bs->opaque; - int ret, index_in_cluster, n; + int ret, index_in_cluster, n, n1; uint64_t cluster_offset; while (nb_sectors > 0) { @@ -712,9 +727,12 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, if (!cluster_offset) { if (bs->backing_hd) { /* read from the base image */ - ret = bdrv_read(bs->backing_hd, sector_num, buf, n); - if (ret < 0) - return -1; + n1 = backing_read1(bs->backing_hd, sector_num, buf, n); + if (n1 > 0) { + ret = bdrv_read(bs->backing_hd, sector_num, buf, n1); + if (ret < 0) + return -1; + } } else { memset(buf, 0, 512 * n); } @@ -815,7 +833,7 @@ static void qcow_aio_read_cb(void *opaque, int ret) BlockDriverState *bs = acb->bs; BDRVQcowState *s = bs->opaque; QCowAIOCB *acb1 = acb->opaque; - int index_in_cluster; + int index_in_cluster, n1; if (ret < 0) { fail: @@ -859,10 +877,16 @@ static void qcow_aio_read_cb(void *opaque, int ret) if (!acb1->cluster_offset) { if (bs->backing_hd) { /* read from the base image */ - ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, - acb1->buf, acb1->n, qcow_aio_read_cb, acb); - if (ret < 0) - goto fail; + n1 = backing_read1(bs->backing_hd, acb1->sector_num, + acb1->buf, acb1->n); + if (n1 > 0) { + ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, + acb1->buf, n1, qcow_aio_read_cb, acb); + if (ret < 0) + goto fail; + } else { + goto redo; + } } else { /* Note: in this case, no need to wait */ memset(acb1->buf, 0, 512 * acb1->n); |