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 | 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 | 714 | static int qcow_read(BlockDriverState *bs, int64_t sector_num, |
700 | 715 | uint8_t *buf, int nb_sectors) |
701 | 716 | { |
702 | 717 | BDRVQcowState *s = bs->opaque; |
703 | - int ret, index_in_cluster, n; | |
718 | + int ret, index_in_cluster, n, n1; | |
704 | 719 | uint64_t cluster_offset; |
705 | 720 | |
706 | 721 | while (nb_sectors > 0) { |
... | ... | @@ -712,9 +727,12 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num, |
712 | 727 | if (!cluster_offset) { |
713 | 728 | if (bs->backing_hd) { |
714 | 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 | 736 | } else { |
719 | 737 | memset(buf, 0, 512 * n); |
720 | 738 | } |
... | ... | @@ -815,7 +833,7 @@ static void qcow_aio_read_cb(void *opaque, int ret) |
815 | 833 | BlockDriverState *bs = acb->bs; |
816 | 834 | BDRVQcowState *s = bs->opaque; |
817 | 835 | QCowAIOCB *acb1 = acb->opaque; |
818 | - int index_in_cluster; | |
836 | + int index_in_cluster, n1; | |
819 | 837 | |
820 | 838 | if (ret < 0) { |
821 | 839 | fail: |
... | ... | @@ -859,10 +877,16 @@ static void qcow_aio_read_cb(void *opaque, int ret) |
859 | 877 | if (!acb1->cluster_offset) { |
860 | 878 | if (bs->backing_hd) { |
861 | 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 | 890 | } else { |
867 | 891 | /* Note: in this case, no need to wait */ |
868 | 892 | memset(acb1->buf, 0, 512 * acb1->n); | ... | ... |