Commit 52d893ecf98a43d17f9b65c5a22a130ecacd9bf1
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); | ... | ... |