Commit 6db6c63826a4a2c06cb02bec2bfce3f506eacda8
1 parent
643e5399
Cleanup {alloc|get}_cluster_offset() (Gleb Natapov)
Move duplicated code into helper functions. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5860 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
73 additions
and
89 deletions
block-qcow2.c
... | ... | @@ -601,6 +601,34 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index) |
601 | 601 | return l2_table; |
602 | 602 | } |
603 | 603 | |
604 | +static int size_to_clusters(BDRVQcowState *s, int64_t size) | |
605 | +{ | |
606 | + return (size + (s->cluster_size - 1)) >> s->cluster_bits; | |
607 | +} | |
608 | + | |
609 | +static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size, | |
610 | + uint64_t *l2_table, uint64_t mask) | |
611 | +{ | |
612 | + int i; | |
613 | + uint64_t offset = be64_to_cpu(l2_table[0]) & ~mask; | |
614 | + | |
615 | + for (i = 0; i < nb_clusters; i++) | |
616 | + if (offset + i * cluster_size != (be64_to_cpu(l2_table[i]) & ~mask)) | |
617 | + break; | |
618 | + | |
619 | + return i; | |
620 | +} | |
621 | + | |
622 | +static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table) | |
623 | +{ | |
624 | + int i = 0; | |
625 | + | |
626 | + while(nb_clusters-- && l2_table[i] == 0) | |
627 | + i++; | |
628 | + | |
629 | + return i; | |
630 | +} | |
631 | + | |
604 | 632 | /* |
605 | 633 | * get_cluster_offset |
606 | 634 | * |
... | ... | @@ -622,9 +650,9 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, |
622 | 650 | { |
623 | 651 | BDRVQcowState *s = bs->opaque; |
624 | 652 | int l1_index, l2_index; |
625 | - uint64_t l2_offset, *l2_table, cluster_offset, next; | |
626 | - int l1_bits; | |
627 | - int index_in_cluster, nb_available, nb_needed; | |
653 | + uint64_t l2_offset, *l2_table, cluster_offset; | |
654 | + int l1_bits, c; | |
655 | + int index_in_cluster, nb_available, nb_needed, nb_clusters; | |
628 | 656 | |
629 | 657 | index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1); |
630 | 658 | nb_needed = *num + index_in_cluster; |
... | ... | @@ -632,7 +660,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, |
632 | 660 | l1_bits = s->l2_bits + s->cluster_bits; |
633 | 661 | |
634 | 662 | /* compute how many bytes there are between the offset and |
635 | - * and the end of the l1 entry | |
663 | + * the end of the l1 entry | |
636 | 664 | */ |
637 | 665 | |
638 | 666 | nb_available = (1 << l1_bits) - (offset & ((1 << l1_bits) - 1)); |
... | ... | @@ -667,38 +695,25 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, |
667 | 695 | |
668 | 696 | l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); |
669 | 697 | cluster_offset = be64_to_cpu(l2_table[l2_index]); |
670 | - nb_available = s->cluster_sectors; | |
671 | - l2_index++; | |
698 | + nb_clusters = size_to_clusters(s, nb_needed << 9); | |
672 | 699 | |
673 | 700 | if (!cluster_offset) { |
674 | - | |
675 | - /* how many empty clusters ? */ | |
676 | - | |
677 | - while (nb_available < nb_needed && !l2_table[l2_index]) { | |
678 | - l2_index++; | |
679 | - nb_available += s->cluster_sectors; | |
680 | - } | |
701 | + /* how many empty clusters ? */ | |
702 | + c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]); | |
681 | 703 | } else { |
704 | + /* how many allocated clusters ? */ | |
705 | + c = count_contiguous_clusters(nb_clusters, s->cluster_size, | |
706 | + &l2_table[l2_index], QCOW_OFLAG_COPIED); | |
707 | + } | |
682 | 708 | |
683 | - /* how many allocated clusters ? */ | |
684 | - | |
685 | - cluster_offset &= ~QCOW_OFLAG_COPIED; | |
686 | - while (nb_available < nb_needed) { | |
687 | - next = be64_to_cpu(l2_table[l2_index]) & ~QCOW_OFLAG_COPIED; | |
688 | - if (next != cluster_offset + (nb_available << 9)) | |
689 | - break; | |
690 | - l2_index++; | |
691 | - nb_available += s->cluster_sectors; | |
692 | - } | |
693 | - } | |
694 | - | |
709 | + nb_available = (c * s->cluster_sectors); | |
695 | 710 | out: |
696 | 711 | if (nb_available > nb_needed) |
697 | 712 | nb_available = nb_needed; |
698 | 713 | |
699 | 714 | *num = nb_available - index_in_cluster; |
700 | 715 | |
701 | - return cluster_offset; | |
716 | + return cluster_offset & ~QCOW_OFLAG_COPIED; | |
702 | 717 | } |
703 | 718 | |
704 | 719 | /* |
... | ... | @@ -862,15 +877,15 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs, |
862 | 877 | BDRVQcowState *s = bs->opaque; |
863 | 878 | int l2_index, ret; |
864 | 879 | uint64_t l2_offset, *l2_table, cluster_offset; |
865 | - int nb_available, nb_clusters, i, j; | |
866 | - uint64_t start_sect, current; | |
880 | + int nb_available, nb_clusters, i = 0; | |
881 | + uint64_t start_sect; | |
867 | 882 | |
868 | 883 | ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index); |
869 | 884 | if (ret == 0) |
870 | 885 | return 0; |
871 | 886 | |
872 | - nb_clusters = ((n_end << 9) + s->cluster_size - 1) >> | |
873 | - s->cluster_bits; | |
887 | + nb_clusters = size_to_clusters(s, n_end << 9); | |
888 | + | |
874 | 889 | if (nb_clusters > s->l2_size - l2_index) |
875 | 890 | nb_clusters = s->l2_size - l2_index; |
876 | 891 | |
... | ... | @@ -879,13 +894,8 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs, |
879 | 894 | /* We keep all QCOW_OFLAG_COPIED clusters */ |
880 | 895 | |
881 | 896 | if (cluster_offset & QCOW_OFLAG_COPIED) { |
882 | - | |
883 | - for (i = 1; i < nb_clusters; i++) { | |
884 | - current = be64_to_cpu(l2_table[l2_index + i]); | |
885 | - if (cluster_offset + (i << s->cluster_bits) != current) | |
886 | - break; | |
887 | - } | |
888 | - nb_clusters = i; | |
897 | + nb_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size, | |
898 | + &l2_table[l2_index], 0); | |
889 | 899 | |
890 | 900 | nb_available = nb_clusters << (s->cluster_bits - 9); |
891 | 901 | if (nb_available > n_end) |
... | ... | @@ -903,46 +913,27 @@ static uint64_t alloc_cluster_offset(BlockDriverState *bs, |
903 | 913 | |
904 | 914 | /* how many available clusters ? */ |
905 | 915 | |
906 | - i = 0; | |
907 | 916 | while (i < nb_clusters) { |
917 | + int j; | |
918 | + i += count_contiguous_free_clusters(nb_clusters - i, | |
919 | + &l2_table[l2_index + i]); | |
908 | 920 | |
909 | - i++; | |
910 | - | |
911 | - if (!cluster_offset) { | |
912 | - | |
913 | - /* how many free clusters ? */ | |
914 | - | |
915 | - while (i < nb_clusters) { | |
916 | - cluster_offset = be64_to_cpu(l2_table[l2_index + i]); | |
917 | - if (cluster_offset != 0) | |
918 | - break; | |
919 | - i++; | |
920 | - } | |
921 | + cluster_offset = be64_to_cpu(l2_table[l2_index + i]); | |
921 | 922 | |
922 | - if ((cluster_offset & QCOW_OFLAG_COPIED) || | |
923 | + if ((cluster_offset & QCOW_OFLAG_COPIED) || | |
923 | 924 | (cluster_offset & QCOW_OFLAG_COMPRESSED)) |
924 | - break; | |
925 | - | |
926 | - } else { | |
925 | + break; | |
927 | 926 | |
928 | - /* how many contiguous clusters ? */ | |
927 | + j = count_contiguous_clusters(nb_clusters - i, s->cluster_size, | |
928 | + &l2_table[l2_index + i], 0); | |
929 | 929 | |
930 | - j = 1; | |
931 | - current = 0; | |
932 | - while (i < nb_clusters) { | |
933 | - current = be64_to_cpu(l2_table[l2_index + i]); | |
934 | - if (cluster_offset + (j << s->cluster_bits) != current) | |
935 | - break; | |
930 | + if (j) | |
931 | + free_any_clusters(bs, cluster_offset, j); | |
936 | 932 | |
937 | - i++; | |
938 | - j++; | |
939 | - } | |
933 | + i += j; | |
940 | 934 | |
941 | - free_any_clusters(bs, cluster_offset, j); | |
942 | - if (current) | |
943 | - break; | |
944 | - cluster_offset = current; | |
945 | - } | |
935 | + if(be64_to_cpu(l2_table[l2_index + i])) | |
936 | + break; | |
946 | 937 | } |
947 | 938 | nb_clusters = i; |
948 | 939 | |
... | ... | @@ -2194,26 +2185,19 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size) |
2194 | 2185 | BDRVQcowState *s = bs->opaque; |
2195 | 2186 | int i, nb_clusters; |
2196 | 2187 | |
2197 | - nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits; | |
2198 | - for(;;) { | |
2199 | - if (get_refcount(bs, s->free_cluster_index) == 0) { | |
2200 | - s->free_cluster_index++; | |
2201 | - for(i = 1; i < nb_clusters; i++) { | |
2202 | - if (get_refcount(bs, s->free_cluster_index) != 0) | |
2203 | - goto not_found; | |
2204 | - s->free_cluster_index++; | |
2205 | - } | |
2188 | + nb_clusters = size_to_clusters(s, size); | |
2189 | +retry: | |
2190 | + for(i = 0; i < nb_clusters; i++) { | |
2191 | + int64_t i = s->free_cluster_index++; | |
2192 | + if (get_refcount(bs, i) != 0) | |
2193 | + goto retry; | |
2194 | + } | |
2206 | 2195 | #ifdef DEBUG_ALLOC2 |
2207 | - printf("alloc_clusters: size=%lld -> %lld\n", | |
2208 | - size, | |
2209 | - (s->free_cluster_index - nb_clusters) << s->cluster_bits); | |
2196 | + printf("alloc_clusters: size=%lld -> %lld\n", | |
2197 | + size, | |
2198 | + (s->free_cluster_index - nb_clusters) << s->cluster_bits); | |
2210 | 2199 | #endif |
2211 | - return (s->free_cluster_index - nb_clusters) << s->cluster_bits; | |
2212 | - } else { | |
2213 | - not_found: | |
2214 | - s->free_cluster_index++; | |
2215 | - } | |
2216 | - } | |
2200 | + return (s->free_cluster_index - nb_clusters) << s->cluster_bits; | |
2217 | 2201 | } |
2218 | 2202 | |
2219 | 2203 | static int64_t alloc_clusters(BlockDriverState *bs, int64_t size) |
... | ... | @@ -2548,7 +2532,7 @@ static void check_refcounts(BlockDriverState *bs) |
2548 | 2532 | uint16_t *refcount_table; |
2549 | 2533 | |
2550 | 2534 | size = bdrv_getlength(s->hd); |
2551 | - nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits; | |
2535 | + nb_clusters = size_to_clusters(s, size); | |
2552 | 2536 | refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t)); |
2553 | 2537 | |
2554 | 2538 | /* header */ |
... | ... | @@ -2600,7 +2584,7 @@ static void dump_refcounts(BlockDriverState *bs) |
2600 | 2584 | int refcount; |
2601 | 2585 | |
2602 | 2586 | size = bdrv_getlength(s->hd); |
2603 | - nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits; | |
2587 | + nb_clusters = size_to_clusters(s, size); | |
2604 | 2588 | for(k = 0; k < nb_clusters;) { |
2605 | 2589 | k1 = k; |
2606 | 2590 | refcount = get_refcount(bs, k); | ... | ... |