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,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 BDRVQcowState *s = bs->opaque; 699 BDRVQcowState *s = bs->opaque;
673 int l1_index, l2_index, ret; 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 /* seek the the l2 offset in the l1 table */ 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,47 +730,97 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs,
703 /* find the cluster offset for the given disk offset */ 730 /* find the cluster offset for the given disk offset */
704 731
705 l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); 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 if (cluster_offset & QCOW_OFLAG_COPIED) 768 if (cluster_offset & QCOW_OFLAG_COPIED)
709 return cluster_offset & ~QCOW_OFLAG_COPIED; 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 /* allocate a new cluster */ 825 /* allocate a new cluster */
749 826
@@ -916,7 +993,7 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num, @@ -916,7 +993,7 @@ static int qcow_write(BlockDriverState *bs, int64_t sector_num,
916 n = s->cluster_sectors - index_in_cluster; 993 n = s->cluster_sectors - index_in_cluster;
917 if (n > nb_sectors) 994 if (n > nb_sectors)
918 n = nb_sectors; 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 index_in_cluster, 997 index_in_cluster,
921 index_in_cluster + n); 998 index_in_cluster + n);
922 if (!cluster_offset) 999 if (!cluster_offset)
@@ -1100,7 +1177,7 @@ static void qcow_aio_write_cb(void *opaque, int ret) @@ -1100,7 +1177,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
1100 acb->n = s->cluster_sectors - index_in_cluster; 1177 acb->n = s->cluster_sectors - index_in_cluster;
1101 if (acb->n > acb->nb_sectors) 1178 if (acb->n > acb->nb_sectors)
1102 acb->n = acb->nb_sectors; 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 index_in_cluster, 1181 index_in_cluster,
1105 index_in_cluster + acb->n); 1182 index_in_cluster + acb->n);
1106 if (!cluster_offset || (cluster_offset & 511) != 0) { 1183 if (!cluster_offset || (cluster_offset & 511) != 0) {
@@ -1362,8 +1439,10 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, @@ -1362,8 +1439,10 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
1362 /* could not compress: write normal cluster */ 1439 /* could not compress: write normal cluster */
1363 qcow_write(bs, sector_num, buf, s->cluster_sectors); 1440 qcow_write(bs, sector_num, buf, s->cluster_sectors);
1364 } else { 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 cluster_offset &= s->cluster_offset_mask; 1446 cluster_offset &= s->cluster_offset_mask;
1368 if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) { 1447 if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
1369 qemu_free(out_buf); 1448 qemu_free(out_buf);