diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 80 |
1 files changed, 56 insertions, 24 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index dd0fcfcb35ce..ef97f19c2f9d 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -627,21 +627,19 @@ static ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb, | |||
627 | return block; | 627 | return block; |
628 | } | 628 | } |
629 | 629 | ||
630 | static inline void *mb_correct_addr_and_bit(int *bit, void *addr) | ||
631 | { | ||
630 | #if BITS_PER_LONG == 64 | 632 | #if BITS_PER_LONG == 64 |
631 | #define mb_correct_addr_and_bit(bit, addr) \ | 633 | *bit += ((unsigned long) addr & 7UL) << 3; |
632 | { \ | 634 | addr = (void *) ((unsigned long) addr & ~7UL); |
633 | bit += ((unsigned long) addr & 7UL) << 3; \ | ||
634 | addr = (void *) ((unsigned long) addr & ~7UL); \ | ||
635 | } | ||
636 | #elif BITS_PER_LONG == 32 | 635 | #elif BITS_PER_LONG == 32 |
637 | #define mb_correct_addr_and_bit(bit, addr) \ | 636 | *bit += ((unsigned long) addr & 3UL) << 3; |
638 | { \ | 637 | addr = (void *) ((unsigned long) addr & ~3UL); |
639 | bit += ((unsigned long) addr & 3UL) << 3; \ | ||
640 | addr = (void *) ((unsigned long) addr & ~3UL); \ | ||
641 | } | ||
642 | #else | 638 | #else |
643 | #error "how many bits you are?!" | 639 | #error "how many bits you are?!" |
644 | #endif | 640 | #endif |
641 | return addr; | ||
642 | } | ||
645 | 643 | ||
646 | static inline int mb_test_bit(int bit, void *addr) | 644 | static inline int mb_test_bit(int bit, void *addr) |
647 | { | 645 | { |
@@ -649,34 +647,54 @@ static inline int mb_test_bit(int bit, void *addr) | |||
649 | * ext4_test_bit on architecture like powerpc | 647 | * ext4_test_bit on architecture like powerpc |
650 | * needs unsigned long aligned address | 648 | * needs unsigned long aligned address |
651 | */ | 649 | */ |
652 | mb_correct_addr_and_bit(bit, addr); | 650 | addr = mb_correct_addr_and_bit(&bit, addr); |
653 | return ext4_test_bit(bit, addr); | 651 | return ext4_test_bit(bit, addr); |
654 | } | 652 | } |
655 | 653 | ||
656 | static inline void mb_set_bit(int bit, void *addr) | 654 | static inline void mb_set_bit(int bit, void *addr) |
657 | { | 655 | { |
658 | mb_correct_addr_and_bit(bit, addr); | 656 | addr = mb_correct_addr_and_bit(&bit, addr); |
659 | ext4_set_bit(bit, addr); | 657 | ext4_set_bit(bit, addr); |
660 | } | 658 | } |
661 | 659 | ||
662 | static inline void mb_set_bit_atomic(spinlock_t *lock, int bit, void *addr) | 660 | static inline void mb_set_bit_atomic(spinlock_t *lock, int bit, void *addr) |
663 | { | 661 | { |
664 | mb_correct_addr_and_bit(bit, addr); | 662 | addr = mb_correct_addr_and_bit(&bit, addr); |
665 | ext4_set_bit_atomic(lock, bit, addr); | 663 | ext4_set_bit_atomic(lock, bit, addr); |
666 | } | 664 | } |
667 | 665 | ||
668 | static inline void mb_clear_bit(int bit, void *addr) | 666 | static inline void mb_clear_bit(int bit, void *addr) |
669 | { | 667 | { |
670 | mb_correct_addr_and_bit(bit, addr); | 668 | addr = mb_correct_addr_and_bit(&bit, addr); |
671 | ext4_clear_bit(bit, addr); | 669 | ext4_clear_bit(bit, addr); |
672 | } | 670 | } |
673 | 671 | ||
674 | static inline void mb_clear_bit_atomic(spinlock_t *lock, int bit, void *addr) | 672 | static inline void mb_clear_bit_atomic(spinlock_t *lock, int bit, void *addr) |
675 | { | 673 | { |
676 | mb_correct_addr_and_bit(bit, addr); | 674 | addr = mb_correct_addr_and_bit(&bit, addr); |
677 | ext4_clear_bit_atomic(lock, bit, addr); | 675 | ext4_clear_bit_atomic(lock, bit, addr); |
678 | } | 676 | } |
679 | 677 | ||
678 | static inline int mb_find_next_zero_bit(void *addr, int max, int start) | ||
679 | { | ||
680 | int fix = 0; | ||
681 | addr = mb_correct_addr_and_bit(&fix, addr); | ||
682 | max += fix; | ||
683 | start += fix; | ||
684 | |||
685 | return ext4_find_next_zero_bit(addr, max, start) - fix; | ||
686 | } | ||
687 | |||
688 | static inline int mb_find_next_bit(void *addr, int max, int start) | ||
689 | { | ||
690 | int fix = 0; | ||
691 | addr = mb_correct_addr_and_bit(&fix, addr); | ||
692 | max += fix; | ||
693 | start += fix; | ||
694 | |||
695 | return ext4_find_next_bit(addr, max, start) - fix; | ||
696 | } | ||
697 | |||
680 | static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) | 698 | static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) |
681 | { | 699 | { |
682 | char *bb; | 700 | char *bb; |
@@ -906,7 +924,7 @@ static void ext4_mb_mark_free_simple(struct super_block *sb, | |||
906 | unsigned short chunk; | 924 | unsigned short chunk; |
907 | unsigned short border; | 925 | unsigned short border; |
908 | 926 | ||
909 | BUG_ON(len >= EXT4_BLOCKS_PER_GROUP(sb)); | 927 | BUG_ON(len > EXT4_BLOCKS_PER_GROUP(sb)); |
910 | 928 | ||
911 | border = 2 << sb->s_blocksize_bits; | 929 | border = 2 << sb->s_blocksize_bits; |
912 | 930 | ||
@@ -946,12 +964,12 @@ static void ext4_mb_generate_buddy(struct super_block *sb, | |||
946 | 964 | ||
947 | /* initialize buddy from bitmap which is aggregation | 965 | /* initialize buddy from bitmap which is aggregation |
948 | * of on-disk bitmap and preallocations */ | 966 | * of on-disk bitmap and preallocations */ |
949 | i = ext4_find_next_zero_bit(bitmap, max, 0); | 967 | i = mb_find_next_zero_bit(bitmap, max, 0); |
950 | grp->bb_first_free = i; | 968 | grp->bb_first_free = i; |
951 | while (i < max) { | 969 | while (i < max) { |
952 | fragments++; | 970 | fragments++; |
953 | first = i; | 971 | first = i; |
954 | i = ext4_find_next_bit(bitmap, max, i); | 972 | i = mb_find_next_bit(bitmap, max, i); |
955 | len = i - first; | 973 | len = i - first; |
956 | free += len; | 974 | free += len; |
957 | if (len > 1) | 975 | if (len > 1) |
@@ -959,7 +977,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb, | |||
959 | else | 977 | else |
960 | grp->bb_counters[0]++; | 978 | grp->bb_counters[0]++; |
961 | if (i < max) | 979 | if (i < max) |
962 | i = ext4_find_next_zero_bit(bitmap, max, i); | 980 | i = mb_find_next_zero_bit(bitmap, max, i); |
963 | } | 981 | } |
964 | grp->bb_fragments = fragments; | 982 | grp->bb_fragments = fragments; |
965 | 983 | ||
@@ -967,6 +985,10 @@ static void ext4_mb_generate_buddy(struct super_block *sb, | |||
967 | ext4_error(sb, __FUNCTION__, | 985 | ext4_error(sb, __FUNCTION__, |
968 | "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n", | 986 | "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n", |
969 | group, free, grp->bb_free); | 987 | group, free, grp->bb_free); |
988 | /* | ||
989 | * If we intent to continue, we consider group descritor | ||
990 | * corrupt and update bb_free using bitmap value | ||
991 | */ | ||
970 | grp->bb_free = free; | 992 | grp->bb_free = free; |
971 | } | 993 | } |
972 | 994 | ||
@@ -1778,7 +1800,7 @@ static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, | |||
1778 | buddy = mb_find_buddy(e4b, i, &max); | 1800 | buddy = mb_find_buddy(e4b, i, &max); |
1779 | BUG_ON(buddy == NULL); | 1801 | BUG_ON(buddy == NULL); |
1780 | 1802 | ||
1781 | k = ext4_find_next_zero_bit(buddy, max, 0); | 1803 | k = mb_find_next_zero_bit(buddy, max, 0); |
1782 | BUG_ON(k >= max); | 1804 | BUG_ON(k >= max); |
1783 | 1805 | ||
1784 | ac->ac_found++; | 1806 | ac->ac_found++; |
@@ -1818,11 +1840,11 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1818 | i = e4b->bd_info->bb_first_free; | 1840 | i = e4b->bd_info->bb_first_free; |
1819 | 1841 | ||
1820 | while (free && ac->ac_status == AC_STATUS_CONTINUE) { | 1842 | while (free && ac->ac_status == AC_STATUS_CONTINUE) { |
1821 | i = ext4_find_next_zero_bit(bitmap, | 1843 | i = mb_find_next_zero_bit(bitmap, |
1822 | EXT4_BLOCKS_PER_GROUP(sb), i); | 1844 | EXT4_BLOCKS_PER_GROUP(sb), i); |
1823 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { | 1845 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { |
1824 | /* | 1846 | /* |
1825 | * IF we corrupt the bitmap we won't find any | 1847 | * IF we have corrupt bitmap, we won't find any |
1826 | * free blocks even though group info says we | 1848 | * free blocks even though group info says we |
1827 | * we have free blocks | 1849 | * we have free blocks |
1828 | */ | 1850 | */ |
@@ -1838,6 +1860,12 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1838 | ext4_error(sb, __FUNCTION__, "%d free blocks as per " | 1860 | ext4_error(sb, __FUNCTION__, "%d free blocks as per " |
1839 | "group info. But got %d blocks\n", | 1861 | "group info. But got %d blocks\n", |
1840 | free, ex.fe_len); | 1862 | free, ex.fe_len); |
1863 | /* | ||
1864 | * The number of free blocks differs. This mostly | ||
1865 | * indicate that the bitmap is corrupt. So exit | ||
1866 | * without claiming the space. | ||
1867 | */ | ||
1868 | break; | ||
1841 | } | 1869 | } |
1842 | 1870 | ||
1843 | ext4_mb_measure_extent(ac, &ex, e4b); | 1871 | ext4_mb_measure_extent(ac, &ex, e4b); |
@@ -3740,10 +3768,10 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b, | |||
3740 | } | 3768 | } |
3741 | 3769 | ||
3742 | while (bit < end) { | 3770 | while (bit < end) { |
3743 | bit = ext4_find_next_zero_bit(bitmap_bh->b_data, end, bit); | 3771 | bit = mb_find_next_zero_bit(bitmap_bh->b_data, end, bit); |
3744 | if (bit >= end) | 3772 | if (bit >= end) |
3745 | break; | 3773 | break; |
3746 | next = ext4_find_next_bit(bitmap_bh->b_data, end, bit); | 3774 | next = mb_find_next_bit(bitmap_bh->b_data, end, bit); |
3747 | if (next > end) | 3775 | if (next > end) |
3748 | next = end; | 3776 | next = end; |
3749 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + | 3777 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + |
@@ -3771,6 +3799,10 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b, | |||
3771 | (unsigned long) pa->pa_len); | 3799 | (unsigned long) pa->pa_len); |
3772 | ext4_error(sb, __FUNCTION__, "free %u, pa_free %u\n", | 3800 | ext4_error(sb, __FUNCTION__, "free %u, pa_free %u\n", |
3773 | free, pa->pa_free); | 3801 | free, pa->pa_free); |
3802 | /* | ||
3803 | * pa is already deleted so we use the value obtained | ||
3804 | * from the bitmap and continue. | ||
3805 | */ | ||
3774 | } | 3806 | } |
3775 | atomic_add(free, &sbi->s_mb_discarded); | 3807 | atomic_add(free, &sbi->s_mb_discarded); |
3776 | if (ac) | 3808 | if (ac) |