diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-02-23 01:38:34 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-02-23 01:38:34 -0500 |
commit | ffad0a44b7216d0f079dcf95a351082099d1e5fb (patch) | |
tree | cfbcc86fbce071b89c51d9d55de8fe39876c79cf /fs/ext4/mballoc.c | |
parent | 42bf0383d1e09dd1b38f3debb13a76b2f87634b3 (diff) |
ext4: ext4_find_next_zero_bit needs an aligned address on some arch
ext4_find_next_zero_bit and ext4_find_next_bit needs a long aligned
address on x8_64. Add mb_find_next_zero_bit and mb_find_next_bit
and use them in the mballoc.
Fix: https://bugzilla.redhat.com/show_bug.cgi?id=433286
Eric Sandeen debugged the problem and suggested the fix.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Acked-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 62 |
1 files changed, 40 insertions, 22 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6968c53e62ad..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; |
@@ -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 | ||
@@ -1782,7 +1800,7 @@ static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, | |||
1782 | buddy = mb_find_buddy(e4b, i, &max); | 1800 | buddy = mb_find_buddy(e4b, i, &max); |
1783 | BUG_ON(buddy == NULL); | 1801 | BUG_ON(buddy == NULL); |
1784 | 1802 | ||
1785 | k = ext4_find_next_zero_bit(buddy, max, 0); | 1803 | k = mb_find_next_zero_bit(buddy, max, 0); |
1786 | BUG_ON(k >= max); | 1804 | BUG_ON(k >= max); |
1787 | 1805 | ||
1788 | ac->ac_found++; | 1806 | ac->ac_found++; |
@@ -1822,7 +1840,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1822 | i = e4b->bd_info->bb_first_free; | 1840 | i = e4b->bd_info->bb_first_free; |
1823 | 1841 | ||
1824 | while (free && ac->ac_status == AC_STATUS_CONTINUE) { | 1842 | while (free && ac->ac_status == AC_STATUS_CONTINUE) { |
1825 | i = ext4_find_next_zero_bit(bitmap, | 1843 | i = mb_find_next_zero_bit(bitmap, |
1826 | EXT4_BLOCKS_PER_GROUP(sb), i); | 1844 | EXT4_BLOCKS_PER_GROUP(sb), i); |
1827 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { | 1845 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { |
1828 | /* | 1846 | /* |
@@ -3750,10 +3768,10 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b, | |||
3750 | } | 3768 | } |
3751 | 3769 | ||
3752 | while (bit < end) { | 3770 | while (bit < end) { |
3753 | 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); |
3754 | if (bit >= end) | 3772 | if (bit >= end) |
3755 | break; | 3773 | break; |
3756 | next = ext4_find_next_bit(bitmap_bh->b_data, end, bit); | 3774 | next = mb_find_next_bit(bitmap_bh->b_data, end, bit); |
3757 | if (next > end) | 3775 | if (next > end) |
3758 | next = end; | 3776 | next = end; |
3759 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + | 3777 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + |