Commit 52d893ecf98a43d17f9b65c5a22a130ecacd9bf1

Authored by aliguori
1 parent 05203524

Extract compressing part from alloc_cluster_offset() (Laurent Vivier)

Divide alloc_cluster_offset() into alloc_cluster_offset() and
alloc_compressed_cluster_offset().
Common parts are moved to free_any_clusters() and get_cluster_table();

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@5005 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 124 additions and 45 deletions
block-qcow2.c
... ... @@ -652,26 +652,53 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset)
652 652 }
653 653  
654 654 /*
655   - * alloc_cluster_offset
  655 + * free_any_clusters
656 656 *
657   - * For a given offset of the disk image, return cluster offset in
658   - * qcow2 file.
  657 + * free clusters according to its type: compressed or not
659 658 *
660   - * If the offset is not found, allocate a new cluster.
  659 + */
  660 +
  661 +static void free_any_clusters(BlockDriverState *bs,
  662 + uint64_t cluster_offset)
  663 +{
  664 + BDRVQcowState *s = bs->opaque;
  665 +
  666 + if (cluster_offset == 0)
  667 + return;
  668 +
  669 + /* free the cluster */
  670 +
  671 + if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
  672 + int nb_csectors;
  673 + nb_csectors = ((cluster_offset >> s->csize_shift) &
  674 + s->csize_mask) + 1;
  675 + free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511,
  676 + nb_csectors * 512);
  677 + return;
  678 + }
  679 +
  680 + free_clusters(bs, cluster_offset, s->cluster_size);
  681 +}
  682 +
  683 +/*
  684 + * get_cluster_table
661 685 *
662   - * Return the cluster offset if successful,
663   - * Return 0, otherwise.
  686 + * for a given disk offset, load (and allocate if needed)
  687 + * the l2 table.
  688 + *
  689 + * the l2 table offset in the qcow2 file and the cluster index
  690 + * in the l2 table are given to the caller.
664 691 *
665 692 */
666 693  
667   -static uint64_t alloc_cluster_offset(BlockDriverState *bs,
668   - uint64_t offset,
669   - int compressed_size,
670   - int n_start, int n_end)
  694 +static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
  695 + uint64_t **new_l2_table,
  696 + uint64_t *new_l2_offset,
  697 + int *new_l2_index)
671 698 {
672 699 BDRVQcowState *s = bs->opaque;
673 700 int l1_index, l2_index, ret;
674   - uint64_t l2_offset, *l2_table, cluster_offset;
  701 + uint64_t l2_offset, *l2_table;
675 702  
676 703 /* seek the the l2 offset in the l1 table */
677 704  
... ... @@ -703,47 +730,97 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs,
703 730 /* find the cluster offset for the given disk offset */
704 731  
705 732 l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
706   - cluster_offset = be64_to_cpu(l2_table[l2_index]);
707 733  
  734 + *new_l2_table = l2_table;
  735 + *new_l2_offset = l2_offset;
  736 + *new_l2_index = l2_index;
  737 +
  738 + return 1;
  739 +}
  740 +
  741 +/*
  742 + * alloc_compressed_cluster_offset
  743 + *
  744 + * For a given offset of the disk image, return cluster offset in
  745 + * qcow2 file.
  746 + *
  747 + * If the offset is not found, allocate a new compressed cluster.
  748 + *
  749 + * Return the cluster offset if successful,
  750 + * Return 0, otherwise.
  751 + *
  752 + */
  753 +
  754 +static uint64_t alloc_compressed_cluster_offset(BlockDriverState *bs,
  755 + uint64_t offset,
  756 + int compressed_size)
  757 +{
  758 + BDRVQcowState *s = bs->opaque;
  759 + int l2_index, ret;
  760 + uint64_t l2_offset, *l2_table, cluster_offset;
  761 + int nb_csectors;
  762 +
  763 + ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
  764 + if (ret == 0)
  765 + return 0;
  766 +
  767 + cluster_offset = be64_to_cpu(l2_table[l2_index]);
708 768 if (cluster_offset & QCOW_OFLAG_COPIED)
709 769 return cluster_offset & ~QCOW_OFLAG_COPIED;
710 770  
711   - if (cluster_offset) {
712   - /* free the cluster */
713   - if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
714   - int nb_csectors;
715   - nb_csectors = ((cluster_offset >> s->csize_shift) &
716   - s->csize_mask) + 1;
717   - free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511,
718   - nb_csectors * 512);
719   - } else {
720   - free_clusters(bs, cluster_offset, s->cluster_size);
721   - }
722   - }
  771 + free_any_clusters(bs, cluster_offset);
723 772  
724   - if (compressed_size) {
725   - int nb_csectors;
  773 + cluster_offset = alloc_bytes(bs, compressed_size);
  774 + nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
  775 + (cluster_offset >> 9);
726 776  
727   - cluster_offset = alloc_bytes(bs, compressed_size);
728   - nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
729   - (cluster_offset >> 9);
  777 + cluster_offset |= QCOW_OFLAG_COMPRESSED |
  778 + ((uint64_t)nb_csectors << s->csize_shift);
730 779  
731   - cluster_offset |= QCOW_OFLAG_COMPRESSED |
732   - ((uint64_t)nb_csectors << s->csize_shift);
  780 + /* update L2 table */
733 781  
734   - /* update L2 table */
  782 + /* compressed clusters never have the copied flag */
735 783  
736   - /* compressed clusters never have the copied flag */
  784 + l2_table[l2_index] = cpu_to_be64(cluster_offset);
  785 + if (bdrv_pwrite(s->hd,
  786 + l2_offset + l2_index * sizeof(uint64_t),
  787 + l2_table + l2_index,
  788 + sizeof(uint64_t)) != sizeof(uint64_t))
  789 + return 0;
737 790  
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;
  791 + return cluster_offset;
  792 +}
744 793  
745   - return cluster_offset;
746   - }
  794 +/*
  795 + * alloc_cluster_offset
  796 + *
  797 + * For a given offset of the disk image, return cluster offset in
  798 + * qcow2 file.
  799 + *
  800 + * If the offset is not found, allocate a new cluster.
  801 + *
  802 + * Return the cluster offset if successful,
  803 + * Return 0, otherwise.
  804 + *
  805 + */
  806 +
  807 +static uint64_t alloc_cluster_offset(BlockDriverState *bs,
  808 + uint64_t offset,
  809 + int n_start, int n_end)
  810 +{
  811 + BDRVQcowState *s = bs->opaque;
  812 + int l2_index, ret;
  813 + uint64_t l2_offset, *l2_table, cluster_offset;
  814 +
  815 + ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
  816 + if (ret == 0)
  817 + return 0;
  818 +
  819 + cluster_offset = be64_to_cpu(l2_table[l2_index]);
  820 + if (cluster_offset & QCOW_OFLAG_COPIED)
  821 + return cluster_offset & ~QCOW_OFLAG_COPIED;
  822 +
  823 + free_any_clusters(bs, cluster_offset);
747 824  
748 825 /* allocate a new cluster */
749 826  
... ... @@ -916,7 +993,7 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
916 993 n = s->cluster_sectors - index_in_cluster;
917 994 if (n > nb_sectors)
918 995 n = nb_sectors;
919   - cluster_offset = alloc_cluster_offset(bs, sector_num << 9, 0,
  996 + cluster_offset = alloc_cluster_offset(bs, sector_num << 9,
920 997 index_in_cluster,
921 998 index_in_cluster + n);
922 999 if (!cluster_offset)
... ... @@ -1100,7 +1177,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
1100 1177 acb->n = s->cluster_sectors - index_in_cluster;
1101 1178 if (acb->n > acb->nb_sectors)
1102 1179 acb->n = acb->nb_sectors;
1103   - cluster_offset = alloc_cluster_offset(bs, acb->sector_num << 9, 0,
  1180 + cluster_offset = alloc_cluster_offset(bs, acb->sector_num << 9,
1104 1181 index_in_cluster,
1105 1182 index_in_cluster + acb->n);
1106 1183 if (!cluster_offset || (cluster_offset & 511) != 0) {
... ... @@ -1362,8 +1439,10 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
1362 1439 /* could not compress: write normal cluster */
1363 1440 qcow_write(bs, sector_num, buf, s->cluster_sectors);
1364 1441 } else {
1365   - cluster_offset = alloc_cluster_offset(bs, sector_num << 9,
1366   - out_len, 0, 0);
  1442 + cluster_offset = alloc_compressed_cluster_offset(bs, sector_num << 9,
  1443 + out_len);
  1444 + if (!cluster_offset)
  1445 + return -1;
1367 1446 cluster_offset &= s->cluster_offset_mask;
1368 1447 if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
1369 1448 qemu_free(out_buf);
... ...