Commit a946592212874f1e214e0db365c29e8de1179847
1 parent
1aacf348
handle read outside the backing file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2093 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
33 additions
and
9 deletions
block-qcow2.c
@@ -696,11 +696,26 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) | @@ -696,11 +696,26 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) | ||
696 | return 0; | 696 | return 0; |
697 | } | 697 | } |
698 | 698 | ||
699 | +/* handle reading after the end of the backing file */ | ||
700 | +static int backing_read1(BlockDriverState *bs, | ||
701 | + int64_t sector_num, uint8_t *buf, int nb_sectors) | ||
702 | +{ | ||
703 | + int n1; | ||
704 | + if ((sector_num + nb_sectors) <= bs->total_sectors) | ||
705 | + return nb_sectors; | ||
706 | + if (sector_num >= bs->total_sectors) | ||
707 | + n1 = 0; | ||
708 | + else | ||
709 | + n1 = bs->total_sectors - sector_num; | ||
710 | + memset(buf + n1 * 512, 0, 512 * (nb_sectors - n1)); | ||
711 | + return n1; | ||
712 | +} | ||
713 | + | ||
699 | static int qcow_read(BlockDriverState *bs, int64_t sector_num, | 714 | static int qcow_read(BlockDriverState *bs, int64_t sector_num, |
700 | uint8_t *buf, int nb_sectors) | 715 | uint8_t *buf, int nb_sectors) |
701 | { | 716 | { |
702 | BDRVQcowState *s = bs->opaque; | 717 | BDRVQcowState *s = bs->opaque; |
703 | - int ret, index_in_cluster, n; | 718 | + int ret, index_in_cluster, n, n1; |
704 | uint64_t cluster_offset; | 719 | uint64_t cluster_offset; |
705 | 720 | ||
706 | while (nb_sectors > 0) { | 721 | while (nb_sectors > 0) { |
@@ -712,9 +727,12 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, | @@ -712,9 +727,12 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, | ||
712 | if (!cluster_offset) { | 727 | if (!cluster_offset) { |
713 | if (bs->backing_hd) { | 728 | if (bs->backing_hd) { |
714 | /* read from the base image */ | 729 | /* read from the base image */ |
715 | - ret = bdrv_read(bs->backing_hd, sector_num, buf, n); | ||
716 | - if (ret < 0) | ||
717 | - return -1; | 730 | + n1 = backing_read1(bs->backing_hd, sector_num, buf, n); |
731 | + if (n1 > 0) { | ||
732 | + ret = bdrv_read(bs->backing_hd, sector_num, buf, n1); | ||
733 | + if (ret < 0) | ||
734 | + return -1; | ||
735 | + } | ||
718 | } else { | 736 | } else { |
719 | memset(buf, 0, 512 * n); | 737 | memset(buf, 0, 512 * n); |
720 | } | 738 | } |
@@ -815,7 +833,7 @@ static void qcow_aio_read_cb(void *opaque, int ret) | @@ -815,7 +833,7 @@ static void qcow_aio_read_cb(void *opaque, int ret) | ||
815 | BlockDriverState *bs = acb->bs; | 833 | BlockDriverState *bs = acb->bs; |
816 | BDRVQcowState *s = bs->opaque; | 834 | BDRVQcowState *s = bs->opaque; |
817 | QCowAIOCB *acb1 = acb->opaque; | 835 | QCowAIOCB *acb1 = acb->opaque; |
818 | - int index_in_cluster; | 836 | + int index_in_cluster, n1; |
819 | 837 | ||
820 | if (ret < 0) { | 838 | if (ret < 0) { |
821 | fail: | 839 | fail: |
@@ -859,10 +877,16 @@ static void qcow_aio_read_cb(void *opaque, int ret) | @@ -859,10 +877,16 @@ static void qcow_aio_read_cb(void *opaque, int ret) | ||
859 | if (!acb1->cluster_offset) { | 877 | if (!acb1->cluster_offset) { |
860 | if (bs->backing_hd) { | 878 | if (bs->backing_hd) { |
861 | /* read from the base image */ | 879 | /* read from the base image */ |
862 | - ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, | ||
863 | - acb1->buf, acb1->n, qcow_aio_read_cb, acb); | ||
864 | - if (ret < 0) | ||
865 | - goto fail; | 880 | + n1 = backing_read1(bs->backing_hd, acb1->sector_num, |
881 | + acb1->buf, acb1->n); | ||
882 | + if (n1 > 0) { | ||
883 | + ret = bdrv_aio_read(acb1->backing_hd_aiocb, acb1->sector_num, | ||
884 | + acb1->buf, n1, qcow_aio_read_cb, acb); | ||
885 | + if (ret < 0) | ||
886 | + goto fail; | ||
887 | + } else { | ||
888 | + goto redo; | ||
889 | + } | ||
866 | } else { | 890 | } else { |
867 | /* Note: in this case, no need to wait */ | 891 | /* Note: in this case, no need to wait */ |
868 | memset(acb1->buf, 0, 512 * acb1->n); | 892 | memset(acb1->buf, 0, 512 * acb1->n); |