aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/balloc.c3
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/mballoc.c28
3 files changed, 31 insertions, 3 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index a40b1f96c021..d9b66c4a26e8 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -356,6 +356,7 @@ void ext4_validate_block_bitmap(struct super_block *sb,
356 struct buffer_head *bh) 356 struct buffer_head *bh)
357{ 357{
358 ext4_fsblk_t blk; 358 ext4_fsblk_t blk;
359 struct ext4_group_info *grp = ext4_get_group_info(sb, block_group);
359 360
360 if (buffer_verified(bh)) 361 if (buffer_verified(bh))
361 return; 362 return;
@@ -366,12 +367,14 @@ void ext4_validate_block_bitmap(struct super_block *sb,
366 ext4_unlock_group(sb, block_group); 367 ext4_unlock_group(sb, block_group);
367 ext4_error(sb, "bg %u: block %llu: invalid block bitmap", 368 ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
368 block_group, blk); 369 block_group, blk);
370 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
369 return; 371 return;
370 } 372 }
371 if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, 373 if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
372 desc, bh))) { 374 desc, bh))) {
373 ext4_unlock_group(sb, block_group); 375 ext4_unlock_group(sb, block_group);
374 ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); 376 ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
377 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
375 return; 378 return;
376 } 379 }
377 set_buffer_verified(bh); 380 set_buffer_verified(bh);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 2e5818267565..02b764b4e635 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2480,9 +2480,12 @@ struct ext4_group_info {
2480 2480
2481#define EXT4_GROUP_INFO_NEED_INIT_BIT 0 2481#define EXT4_GROUP_INFO_NEED_INIT_BIT 0
2482#define EXT4_GROUP_INFO_WAS_TRIMMED_BIT 1 2482#define EXT4_GROUP_INFO_WAS_TRIMMED_BIT 1
2483#define EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT 2
2483 2484
2484#define EXT4_MB_GRP_NEED_INIT(grp) \ 2485#define EXT4_MB_GRP_NEED_INIT(grp) \
2485 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state))) 2486 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
2487#define EXT4_MB_GRP_BBITMAP_CORRUPT(grp) \
2488 (test_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
2486 2489
2487#define EXT4_MB_GRP_WAS_TRIMMED(grp) \ 2490#define EXT4_MB_GRP_WAS_TRIMMED(grp) \
2488 (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state))) 2491 (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index aa7d058e9e48..a41e3ba8cfaa 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -751,13 +751,15 @@ void ext4_mb_generate_buddy(struct super_block *sb,
751 751
752 if (free != grp->bb_free) { 752 if (free != grp->bb_free) {
753 ext4_grp_locked_error(sb, group, 0, 0, 753 ext4_grp_locked_error(sb, group, 0, 0,
754 "%u clusters in bitmap, %u in gd", 754 "%u clusters in bitmap, %u in gd; "
755 "block bitmap corrupt.",
755 free, grp->bb_free); 756 free, grp->bb_free);
756 /* 757 /*
757 * If we intent to continue, we consider group descritor 758 * If we intend to continue, we consider group descriptor
758 * corrupt and update bb_free using bitmap value 759 * corrupt and update bb_free using bitmap value
759 */ 760 */
760 grp->bb_free = free; 761 grp->bb_free = free;
762 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
761 } 763 }
762 mb_set_largest_free_order(sb, grp); 764 mb_set_largest_free_order(sb, grp);
763 765
@@ -1398,6 +1400,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
1398 1400
1399 BUG_ON(last >= (sb->s_blocksize << 3)); 1401 BUG_ON(last >= (sb->s_blocksize << 3));
1400 assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group)); 1402 assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
1403 /* Don't bother if the block group is corrupt. */
1404 if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
1405 return;
1406
1401 mb_check_buddy(e4b); 1407 mb_check_buddy(e4b);
1402 mb_free_blocks_double(inode, e4b, first, count); 1408 mb_free_blocks_double(inode, e4b, first, count);
1403 1409
@@ -1423,7 +1429,11 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
1423 inode ? inode->i_ino : 0, 1429 inode ? inode->i_ino : 0,
1424 blocknr, 1430 blocknr,
1425 "freeing already freed block " 1431 "freeing already freed block "
1426 "(bit %u)", block); 1432 "(bit %u); block bitmap corrupt.",
1433 block);
1434 /* Mark the block group as corrupt. */
1435 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
1436 &e4b->bd_info->bb_state);
1427 mb_regenerate_buddy(e4b); 1437 mb_regenerate_buddy(e4b);
1428 goto done; 1438 goto done;
1429 } 1439 }
@@ -1790,6 +1800,11 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
1790 if (err) 1800 if (err)
1791 return err; 1801 return err;
1792 1802
1803 if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) {
1804 ext4_mb_unload_buddy(e4b);
1805 return 0;
1806 }
1807
1793 ext4_lock_group(ac->ac_sb, group); 1808 ext4_lock_group(ac->ac_sb, group);
1794 max = mb_find_extent(e4b, ac->ac_g_ex.fe_start, 1809 max = mb_find_extent(e4b, ac->ac_g_ex.fe_start,
1795 ac->ac_g_ex.fe_len, &ex); 1810 ac->ac_g_ex.fe_len, &ex);
@@ -1987,6 +2002,9 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
1987 if (cr <= 2 && free < ac->ac_g_ex.fe_len) 2002 if (cr <= 2 && free < ac->ac_g_ex.fe_len)
1988 return 0; 2003 return 0;
1989 2004
2005 if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
2006 return 0;
2007
1990 /* We only do this if the grp has never been initialized */ 2008 /* We only do this if the grp has never been initialized */
1991 if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) { 2009 if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
1992 int ret = ext4_mb_init_group(ac->ac_sb, group); 2010 int ret = ext4_mb_init_group(ac->ac_sb, group);
@@ -4674,6 +4692,10 @@ do_more:
4674 overflow = 0; 4692 overflow = 0;
4675 ext4_get_group_no_and_offset(sb, block, &block_group, &bit); 4693 ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
4676 4694
4695 if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(
4696 ext4_get_group_info(sb, block_group))))
4697 return;
4698
4677 /* 4699 /*
4678 * Check to see if we are freeing blocks across a group 4700 * Check to see if we are freeing blocks across a group
4679 * boundary. 4701 * boundary.