diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-02-10 01:10:04 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-02-10 01:10:04 -0500 |
commit | 26346ff681cb42c1436ed09c44dcae4809470dab (patch) | |
tree | 1f1b8bff59e9aedbd0ad80a51317d5c1e5cbad91 /fs/ext4 | |
parent | 256bdb497c6f562462f1e89fc8e1409f61ef40cb (diff) |
ext4: Don't panic in case of corrupt bitmap
Multiblock allocator calls BUG_ON in many case if the free and used
blocks count obtained looking at the bitmap is different from what
the allocator internally accounted for. Use ext4_error in such case
and don't panic the system.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/mballoc.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 5e3c35191412..dd0fcfcb35ce 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -681,7 +681,6 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) | |||
681 | { | 681 | { |
682 | char *bb; | 682 | char *bb; |
683 | 683 | ||
684 | /* FIXME!! is this needed */ | ||
685 | BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b)); | 684 | BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b)); |
686 | BUG_ON(max == NULL); | 685 | BUG_ON(max == NULL); |
687 | 686 | ||
@@ -965,7 +964,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb, | |||
965 | grp->bb_fragments = fragments; | 964 | grp->bb_fragments = fragments; |
966 | 965 | ||
967 | if (free != grp->bb_free) { | 966 | if (free != grp->bb_free) { |
968 | printk(KERN_DEBUG | 967 | ext4_error(sb, __FUNCTION__, |
969 | "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n", | 968 | "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n", |
970 | group, free, grp->bb_free); | 969 | group, free, grp->bb_free); |
971 | grp->bb_free = free; | 970 | grp->bb_free = free; |
@@ -1822,13 +1821,24 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1822 | i = ext4_find_next_zero_bit(bitmap, | 1821 | i = ext4_find_next_zero_bit(bitmap, |
1823 | EXT4_BLOCKS_PER_GROUP(sb), i); | 1822 | EXT4_BLOCKS_PER_GROUP(sb), i); |
1824 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { | 1823 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { |
1825 | BUG_ON(free != 0); | 1824 | /* |
1825 | * IF we corrupt the bitmap we won't find any | ||
1826 | * free blocks even though group info says we | ||
1827 | * we have free blocks | ||
1828 | */ | ||
1829 | ext4_error(sb, __FUNCTION__, "%d free blocks as per " | ||
1830 | "group info. But bitmap says 0\n", | ||
1831 | free); | ||
1826 | break; | 1832 | break; |
1827 | } | 1833 | } |
1828 | 1834 | ||
1829 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); | 1835 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); |
1830 | BUG_ON(ex.fe_len <= 0); | 1836 | BUG_ON(ex.fe_len <= 0); |
1831 | BUG_ON(free < ex.fe_len); | 1837 | if (free < ex.fe_len) { |
1838 | ext4_error(sb, __FUNCTION__, "%d free blocks as per " | ||
1839 | "group info. But got %d blocks\n", | ||
1840 | free, ex.fe_len); | ||
1841 | } | ||
1832 | 1842 | ||
1833 | ext4_mb_measure_extent(ac, &ex, e4b); | 1843 | ext4_mb_measure_extent(ac, &ex, e4b); |
1834 | 1844 | ||
@@ -3363,13 +3373,10 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, | |||
3363 | ac->ac_pa = pa; | 3373 | ac->ac_pa = pa; |
3364 | 3374 | ||
3365 | /* we don't correct pa_pstart or pa_plen here to avoid | 3375 | /* we don't correct pa_pstart or pa_plen here to avoid |
3366 | * possible race when tte group is being loaded concurrently | 3376 | * possible race when the group is being loaded concurrently |
3367 | * instead we correct pa later, after blocks are marked | 3377 | * instead we correct pa later, after blocks are marked |
3368 | * in on-disk bitmap -- see ext4_mb_release_context() */ | 3378 | * in on-disk bitmap -- see ext4_mb_release_context() |
3369 | /* | 3379 | * Other CPUs are prevented from allocating from this pa by lg_mutex |
3370 | * FIXME!! but the other CPUs can look at this particular | ||
3371 | * pa and think that it have enought free blocks if we | ||
3372 | * don't update pa_free here right ? | ||
3373 | */ | 3380 | */ |
3374 | mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa); | 3381 | mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa); |
3375 | } | 3382 | } |
@@ -3758,13 +3765,13 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b, | |||
3758 | bit = next + 1; | 3765 | bit = next + 1; |
3759 | } | 3766 | } |
3760 | if (free != pa->pa_free) { | 3767 | if (free != pa->pa_free) { |
3761 | printk(KERN_ERR "pa %p: logic %lu, phys. %lu, len %lu\n", | 3768 | printk(KERN_CRIT "pa %p: logic %lu, phys. %lu, len %lu\n", |
3762 | pa, (unsigned long) pa->pa_lstart, | 3769 | pa, (unsigned long) pa->pa_lstart, |
3763 | (unsigned long) pa->pa_pstart, | 3770 | (unsigned long) pa->pa_pstart, |
3764 | (unsigned long) pa->pa_len); | 3771 | (unsigned long) pa->pa_len); |
3765 | printk(KERN_ERR "free %u, pa_free %u\n", free, pa->pa_free); | 3772 | ext4_error(sb, __FUNCTION__, "free %u, pa_free %u\n", |
3773 | free, pa->pa_free); | ||
3766 | } | 3774 | } |
3767 | BUG_ON(free != pa->pa_free); | ||
3768 | atomic_add(free, &sbi->s_mb_discarded); | 3775 | atomic_add(free, &sbi->s_mb_discarded); |
3769 | if (ac) | 3776 | if (ac) |
3770 | kmem_cache_free(ext4_ac_cachep, ac); | 3777 | kmem_cache_free(ext4_ac_cachep, ac); |
@@ -4435,7 +4442,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, | |||
4435 | unsigned long block, unsigned long count, | 4442 | unsigned long block, unsigned long count, |
4436 | int metadata, unsigned long *freed) | 4443 | int metadata, unsigned long *freed) |
4437 | { | 4444 | { |
4438 | struct buffer_head *bitmap_bh = 0; | 4445 | struct buffer_head *bitmap_bh = NULL; |
4439 | struct super_block *sb = inode->i_sb; | 4446 | struct super_block *sb = inode->i_sb; |
4440 | struct ext4_allocation_context *ac = NULL; | 4447 | struct ext4_allocation_context *ac = NULL; |
4441 | struct ext4_group_desc *gdp; | 4448 | struct ext4_group_desc *gdp; |