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); | ... | ... |