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); | ... | ... |