Commit a946592212874f1e214e0db365c29e8de1179847

Authored by bellard
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);