2 fs/ext4/balloc.c | 14 ++++++++------
3 fs/ext4/ext4.h | 6 ++++++
4 fs/ext4/ialloc.c | 37 +++++++++++++++++++++++++++----------
5 fs/ext4/mballoc.c | 22 +++++++++++++++++++++-
6 4 files changed, 62 insertions(+), 17 deletions(-)
8 diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
9 index db5b7a3..c631a37 100644
10 --- a/fs/ext4/balloc.c
11 +++ b/fs/ext4/balloc.c
12 @@ -92,6 +92,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
13 ext4_group_t ngroups = ext4_get_groups_count(sb);
14 unsigned free_blocks, group_blocks;
15 struct ext4_sb_info *sbi = EXT4_SB(sb);
16 + struct ext4_group_info *grp;
19 J_ASSERT_BH(bh, buffer_locked(bh));
20 @@ -99,12 +100,11 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
21 /* If checksum is bad mark all blocks used to prevent allocation
22 * essentially implementing a per-group read-only flag. */
23 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
24 - ext4_error(sb, "Checksum bad for group %u",
25 + ext4_warning(sb, "Checksum bad for group %u",
27 - ext4_free_blks_set(sb, gdp, 0);
28 - ext4_free_inodes_set(sb, gdp, 0);
29 - ext4_itable_unused_set(sb, gdp, 0);
30 - memset(bh->b_data, 0xff, sb->s_blocksize);
31 + grp = ext4_get_group_info(sb, block_group);
32 + set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
33 + set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
36 memset(bh->b_data, 0, sb->s_blocksize);
37 @@ -242,6 +242,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
38 ext4_grpblk_t next_zero_bit;
39 ext4_fsblk_t bitmap_blk;
40 ext4_fsblk_t group_first_block;
41 + struct ext4_group_info *grp = ext4_get_group_info(sb, block_group);
43 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
44 /* with FLEX_BG, the inode/block bitmaps and itable
45 @@ -279,8 +280,9 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
49 - ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
50 + ext4_warning(sb, "Invalid block bitmap - block_group = %d, block = %llu",
51 block_group, bitmap_blk);
52 + set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
56 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
57 index a18fd36..40ad66f 100644
60 @@ -2257,9 +2257,15 @@ struct ext4_group_info {
62 #define EXT4_GROUP_INFO_NEED_INIT_BIT 0
63 #define EXT4_GROUP_INFO_WAS_TRIMMED_BIT 1
64 +#define EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT 2
65 +#define EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT 3
67 #define EXT4_MB_GRP_NEED_INIT(grp) \
68 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
69 +#define EXT4_MB_GRP_BBITMAP_CORRUPT(grp) \
70 + (test_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
71 +#define EXT4_MB_GRP_IBITMAP_CORRUPT(grp) \
72 + (test_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
74 #define EXT4_MB_GRP_WAS_TRIMMED(grp) \
75 (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
76 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
77 index 532dcaa..c9e6b19 100644
78 --- a/fs/ext4/ialloc.c
79 +++ b/fs/ext4/ialloc.c
80 @@ -72,17 +72,17 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
81 struct ext4_group_desc *gdp)
83 struct ext4_sb_info *sbi = EXT4_SB(sb);
84 + struct ext4_group_info *grp;
86 J_ASSERT_BH(bh, buffer_locked(bh));
88 /* If checksum is bad mark all blocks and inodes use to prevent
89 * allocation, essentially implementing a per-group read-only flag. */
90 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
91 - ext4_error(sb, "Checksum bad for group %u", block_group);
92 - ext4_free_blks_set(sb, gdp, 0);
93 - ext4_free_inodes_set(sb, gdp, 0);
94 - ext4_itable_unused_set(sb, gdp, 0);
95 - memset(bh->b_data, 0xff, sb->s_blocksize);
96 + ext4_warning(sb, "Checksum bad for group %u", block_group);
97 + grp = ext4_get_group_info(sb, block_group);
98 + set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
99 + set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
103 @@ -195,6 +195,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
104 struct ext4_super_block *es;
105 struct ext4_sb_info *sbi;
106 int fatal = 0, err, count, cleared;
107 + struct ext4_group_info *grp;
109 if (atomic_read(&inode->i_count) > 1) {
110 printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
111 @@ -238,7 +239,9 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
112 block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
113 bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
114 bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
116 + /* Don't bother if the inode bitmap is corrupt. */
117 + grp = ext4_get_group_info(sb, block_group);
118 + if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || !bitmap_bh)
121 BUFFER_TRACE(bitmap_bh, "get_write_access");
122 @@ -286,8 +289,10 @@ out:
125 ext4_mark_super_dirty(sb);
127 - ext4_error(sb, "bit already cleared for inode %lu", ino);
129 + ext4_warning(sb, "bit already cleared for inode %lu", ino);
130 + set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
135 @@ -820,6 +825,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
138 ext4_group_t flex_group;
139 + struct ext4_group_info *grp;
141 /* Cannot create files in a deleted directory */
142 if (!dir || !dir->i_nlink)
143 @@ -879,10 +885,21 @@ got_group:
147 + grp = ext4_get_group_info(sb, group);
148 + /* Skip groups with already-known suspicious inode tables */
149 + if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
150 + if (++group == ngroups)
154 brelse(inode_bitmap_bh);
155 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
156 - if (!inode_bitmap_bh)
158 + /* Skip groups with suspicious inode tables */
159 + if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || !inode_bitmap_bh) {
160 + if (++group == ngroups)
165 repeat_in_this_group:
166 ino = ext4_find_next_zero_bit((unsigned long *)
167 diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
168 index 1d77581..d19d1ba 100644
169 --- a/fs/ext4/mballoc.c
170 +++ b/fs/ext4/mballoc.c
171 @@ -1322,6 +1322,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
173 BUG_ON(first + count > (sb->s_blocksize << 3));
174 assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
175 + /* Don't bother if the block group is corrupt. */
176 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
180 mb_free_blocks_double(inode, e4b, first, count);
182 @@ -1353,7 +1357,11 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
183 inode ? inode->i_ino : 0,
185 "freeing already freed block "
186 - "(bit %u)", block);
187 + "(bit %u); block bitmap corrupt",
189 + /* Mark the block group as corrupt. */
190 + set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
191 + &e4b->bd_info->bb_state);
193 mb_clear_bit(block, EXT4_MB_BITMAP(e4b));
194 e4b->bd_info->bb_counters[order]++;
195 @@ -1729,6 +1737,11 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
199 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) {
200 + ext4_mb_unload_buddy(e4b);
204 ext4_lock_group(ac->ac_sb, group);
205 max = mb_find_extent(e4b, 0, ac->ac_g_ex.fe_start,
206 ac->ac_g_ex.fe_len, &ex);
207 @@ -1940,6 +1953,9 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
209 BUG_ON(cr < 0 || cr >= 4);
211 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
214 /* We only do this if the grp has never been initialized */
215 if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
216 int ret = ext4_mb_init_group(ac->ac_sb, group);
217 @@ -4781,6 +4797,10 @@ do_more:
219 ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
221 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(
222 + ext4_get_group_info(sb, block_group))))
226 * Check to see if we are freeing blocks across a group