Commit 052035244f66acfa532b730b1444c4b7e8a4f302

Authored by aliguori
1 parent 108534b9

Divide get_cluster_offset() (Laurent Vivier)

Divide get_cluster_offset() into get_cluster_offset() and
alloc_cluster_offset().

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5004 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 132 additions and 76 deletions
block-qcow2.c
... ... @@ -606,22 +606,77 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
606 606 return l2_table;
607 607 }
608 608  
609   -static uint64_t get_cluster_offset(BlockDriverState *bs,
610   - uint64_t offset, int allocate,
611   - int compressed_size,
612   - int n_start, int n_end)
  609 +/*
  610 + * get_cluster_offset
  611 + *
  612 + * For a given offset of the disk image, return cluster offset in
  613 + * qcow2 file.
  614 + *
  615 + * Return 1, if the offset is found
  616 + * Return 0, otherwise.
  617 + *
  618 + */
  619 +
  620 +static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset)
  621 +{
  622 + BDRVQcowState *s = bs->opaque;
  623 + int l1_index, l2_index;
  624 + uint64_t l2_offset, *l2_table, cluster_offset;
  625 +
  626 + /* seek the the l2 offset in the l1 table */
  627 +
  628 + l1_index = offset >> (s->l2_bits + s->cluster_bits);
  629 + if (l1_index >= s->l1_size)
  630 + return 0;
  631 +
  632 + l2_offset = s->l1_table[l1_index];
  633 +
  634 + /* seek the l2 table of the given l2 offset */
  635 +
  636 + if (!l2_offset)
  637 + return 0;
  638 +
  639 + /* load the l2 table in memory */
  640 +
  641 + l2_offset &= ~QCOW_OFLAG_COPIED;
  642 + l2_table = l2_load(bs, l2_offset);
  643 + if (l2_table == NULL)
  644 + return 0;
  645 +
  646 + /* find the cluster offset for the given disk offset */
  647 +
  648 + l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
  649 + cluster_offset = be64_to_cpu(l2_table[l2_index]);
  650 +
  651 + return cluster_offset & ~QCOW_OFLAG_COPIED;
  652 +}
  653 +
  654 +/*
  655 + * alloc_cluster_offset
  656 + *
  657 + * For a given offset of the disk image, return cluster offset in
  658 + * qcow2 file.
  659 + *
  660 + * If the offset is not found, allocate a new cluster.
  661 + *
  662 + * Return the cluster offset if successful,
  663 + * Return 0, otherwise.
  664 + *
  665 + */
  666 +
  667 +static uint64_t alloc_cluster_offset(BlockDriverState *bs,
  668 + uint64_t offset,
  669 + int compressed_size,
  670 + int n_start, int n_end)
613 671 {
614 672 BDRVQcowState *s = bs->opaque;
615 673 int l1_index, l2_index, ret;
616   - uint64_t l2_offset, *l2_table, cluster_offset, tmp;
  674 + uint64_t l2_offset, *l2_table, cluster_offset;
617 675  
618 676 /* seek the the l2 offset in the l1 table */
619 677  
620 678 l1_index = offset >> (s->l2_bits + s->cluster_bits);
621 679 if (l1_index >= s->l1_size) {
622   - /* outside l1 table is allowed: we grow the table if needed */
623   - if (!allocate)
624   - return 0;
625 680 ret = grow_l1_table(bs, l1_index + 1);
626 681 if (ret < 0)
627 682 return 0;
... ... @@ -630,44 +685,30 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
630 685  
631 686 /* seek the l2 table of the given l2 offset */
632 687  
633   - if (!l2_offset) {
634   - /* the l2 table doesn't exist */
635   - if (!allocate)
  688 + if (l2_offset & QCOW_OFLAG_COPIED) {
  689 + /* load the l2 table in memory */
  690 + l2_offset &= ~QCOW_OFLAG_COPIED;
  691 + l2_table = l2_load(bs, l2_offset);
  692 + if (l2_table == NULL)
636 693 return 0;
637   - /* allocate a new l2 table for this offset */
  694 + } else {
  695 + if (l2_offset)
  696 + free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
638 697 l2_table = l2_allocate(bs, l1_index);
639 698 if (l2_table == NULL)
640 699 return 0;
641 700 l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
642   - } else {
643   - /* the l2 table exists */
644   - if (!(l2_offset & QCOW_OFLAG_COPIED) && allocate) {
645   - /* duplicate the l2 table, and free the old table */
646   - free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
647   - l2_table = l2_allocate(bs, l1_index);
648   - if (l2_table == NULL)
649   - return 0;
650   - l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
651   - } else {
652   - /* load the l2 table in memory */
653   - l2_offset &= ~QCOW_OFLAG_COPIED;
654   - l2_table = l2_load(bs, l2_offset);
655   - if (l2_table == NULL)
656   - return 0;
657   - }
658 701 }
659 702  
660 703 /* find the cluster offset for the given disk offset */
661 704  
662 705 l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
663 706 cluster_offset = be64_to_cpu(l2_table[l2_index]);
664   - if (!cluster_offset) {
665   - /* cluster doesn't exist */
666   - if (!allocate)
667   - return 0;
668   - } else if (!(cluster_offset & QCOW_OFLAG_COPIED)) {
669   - if (!allocate)
670   - return cluster_offset;
  707 +
  708 + if (cluster_offset & QCOW_OFLAG_COPIED)
  709 + return cluster_offset & ~QCOW_OFLAG_COPIED;
  710 +
  711 + if (cluster_offset) {
671 712 /* free the cluster */
672 713 if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
673 714 int nb_csectors;
... ... @@ -678,46 +719,62 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
678 719 } else {
679 720 free_clusters(bs, cluster_offset, s->cluster_size);
680 721 }
681   - } else {
682   - cluster_offset &= ~QCOW_OFLAG_COPIED;
683   - return cluster_offset;
684 722 }
685 723  
686   - if (allocate == 1) {
687   - /* allocate a new cluster */
688   - cluster_offset = alloc_clusters(bs, s->cluster_size);
689   -
690   - /* we must initialize the cluster content which won't be
691   - written */
692   - if ((n_end - n_start) < s->cluster_sectors) {
693   - uint64_t start_sect;
694   -
695   - start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
696   - ret = copy_sectors(bs, start_sect,
697   - cluster_offset, 0, n_start);
698   - if (ret < 0)
699   - return 0;
700   - ret = copy_sectors(bs, start_sect,
701   - cluster_offset, n_end, s->cluster_sectors);
702   - if (ret < 0)
703   - return 0;
704   - }
705   - tmp = cpu_to_be64(cluster_offset | QCOW_OFLAG_COPIED);
706   - } else {
  724 + if (compressed_size) {
707 725 int nb_csectors;
  726 +
708 727 cluster_offset = alloc_bytes(bs, compressed_size);
709 728 nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
710   - (cluster_offset >> 9);
  729 + (cluster_offset >> 9);
  730 +
711 731 cluster_offset |= QCOW_OFLAG_COMPRESSED |
712   - ((uint64_t)nb_csectors << s->csize_shift);
  732 + ((uint64_t)nb_csectors << s->csize_shift);
  733 +
  734 + /* update L2 table */
  735 +
713 736 /* compressed clusters never have the copied flag */
714   - tmp = cpu_to_be64(cluster_offset);
  737 +
  738 + l2_table[l2_index] = cpu_to_be64(cluster_offset);
  739 + if (bdrv_pwrite(s->hd,
  740 + l2_offset + l2_index * sizeof(uint64_t),
  741 + l2_table + l2_index,
  742 + sizeof(uint64_t)) != sizeof(uint64_t))
  743 + return 0;
  744 +
  745 + return cluster_offset;
  746 + }
  747 +
  748 + /* allocate a new cluster */
  749 +
  750 + cluster_offset = alloc_clusters(bs, s->cluster_size);
  751 +
  752 + /* we must initialize the cluster content which won't be
  753 + written */
  754 +
  755 + if ((n_end - n_start) < s->cluster_sectors) {
  756 + uint64_t start_sect;
  757 +
  758 + start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
  759 + ret = copy_sectors(bs, start_sect,
  760 + cluster_offset, 0, n_start);
  761 + if (ret < 0)
  762 + return 0;
  763 + ret = copy_sectors(bs, start_sect,
  764 + cluster_offset, n_end, s->cluster_sectors);
  765 + if (ret < 0)
  766 + return 0;
715 767 }
  768 +
716 769 /* update L2 table */
717   - l2_table[l2_index] = tmp;
  770 +
  771 + l2_table[l2_index] = cpu_to_be64(cluster_offset | QCOW_OFLAG_COPIED);
718 772 if (bdrv_pwrite(s->hd,
719   - l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
  773 + l2_offset + l2_index * sizeof(uint64_t),
  774 + l2_table + l2_index,
  775 + sizeof(uint64_t)) != sizeof(uint64_t))
720 776 return 0;
  777 +
721 778 return cluster_offset;
722 779 }
723 780  
... ... @@ -728,7 +785,7 @@ static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
728 785 int index_in_cluster, n;
729 786 uint64_t cluster_offset;
730 787  
731   - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
  788 + cluster_offset = get_cluster_offset(bs, sector_num << 9);
732 789 index_in_cluster = sector_num & (s->cluster_sectors - 1);
733 790 n = s->cluster_sectors - index_in_cluster;
734 791 if (n > nb_sectors)
... ... @@ -810,7 +867,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
810 867 uint64_t cluster_offset;
811 868  
812 869 while (nb_sectors > 0) {
813   - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
  870 + cluster_offset = get_cluster_offset(bs, sector_num << 9);
814 871 index_in_cluster = sector_num & (s->cluster_sectors - 1);
815 872 n = s->cluster_sectors - index_in_cluster;
816 873 if (n > nb_sectors)
... ... @@ -859,9 +916,9 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
859 916 n = s->cluster_sectors - index_in_cluster;
860 917 if (n > nb_sectors)
861 918 n = nb_sectors;
862   - cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
863   - index_in_cluster,
864   - index_in_cluster + n);
  919 + cluster_offset = alloc_cluster_offset(bs, sector_num << 9, 0,
  920 + index_in_cluster,
  921 + index_in_cluster + n);
865 922 if (!cluster_offset)
866 923 return -1;
867 924 if (s->crypt_method) {
... ... @@ -934,8 +991,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
934 991 }
935 992  
936 993 /* prepare next AIO request */
937   - acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
938   - 0, 0, 0, 0);
  994 + acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9);
939 995 index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
940 996 acb->n = s->cluster_sectors - index_in_cluster;
941 997 if (acb->n > acb->nb_sectors)
... ... @@ -1044,9 +1100,9 @@ static void qcow_aio_write_cb(void *opaque, int ret)
1044 1100 acb->n = s->cluster_sectors - index_in_cluster;
1045 1101 if (acb->n > acb->nb_sectors)
1046 1102 acb->n = acb->nb_sectors;
1047   - cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
1048   - index_in_cluster,
1049   - index_in_cluster + acb->n);
  1103 + cluster_offset = alloc_cluster_offset(bs, acb->sector_num << 9, 0,
  1104 + index_in_cluster,
  1105 + index_in_cluster + acb->n);
1050 1106 if (!cluster_offset || (cluster_offset & 511) != 0) {
1051 1107 ret = -EIO;
1052 1108 goto fail;
... ... @@ -1306,8 +1362,8 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
1306 1362 /* could not compress: write normal cluster */
1307 1363 qcow_write(bs, sector_num, buf, s->cluster_sectors);
1308 1364 } else {
1309   - cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
1310   - out_len, 0, 0);
  1365 + cluster_offset = alloc_cluster_offset(bs, sector_num << 9,
  1366 + out_len, 0, 0);
1311 1367 cluster_offset &= s->cluster_offset_mask;
1312 1368 if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
1313 1369 qemu_free(out_buf);
... ...