1 diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
2 index db5b7a3..332078f 100644
5 @@ -99,12 +99,11 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
6 /* If checksum is bad mark all blocks used to prevent allocation
7 * essentially implementing a per-group read-only flag. */
8 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
9 - ext4_error(sb, "Checksum bad for group %u",
10 + ext4_corrupted_block_group(sb, block_group,
11 + EXT4_GROUP_INFO_BBITMAP_CORRUPT |
12 + EXT4_GROUP_INFO_IBITMAP_CORRUPT,
13 + "Checksum bad for group %u",
15 - ext4_free_blks_set(sb, gdp, 0);
16 - ext4_free_inodes_set(sb, gdp, 0);
17 - ext4_itable_unused_set(sb, gdp, 0);
18 - memset(bh->b_data, 0xff, sb->s_blocksize);
21 memset(bh->b_data, 0, sb->s_blocksize);
22 @@ -279,8 +278,10 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
26 - ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
27 - block_group, bitmap_blk);
28 + ext4_corrupted_block_group(sb, block_group,
29 + EXT4_GROUP_INFO_BBITMAP_CORRUPT,
30 + "Invalid block bitmap - block_group = %d, block = %llu",
31 + block_group, bitmap_blk);
35 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
36 index a18fd36..949d7be 100644
39 @@ -78,6 +78,18 @@ typedef __u32 ext4_lblk_t;
40 /* data type for block group number */
41 typedef unsigned int ext4_group_t;
43 +void __ext4_corrupted_block_group(struct super_block *sb,
44 + ext4_group_t group, unsigned int flags,
45 + const char *function,
48 +#define ext4_corrupted_block_group(sb, group, flags, fmt...) \
50 + __ext4_warning(sb, __func__, __LINE__, ## fmt); \
51 + __ext4_corrupted_block_group(sb, group, flags, \
52 + __func__, __LINE__); \
56 * Flags used in mballoc's allocation_context flags field.
58 @@ -2257,9 +2269,19 @@ struct ext4_group_info {
60 #define EXT4_GROUP_INFO_NEED_INIT_BIT 0
61 #define EXT4_GROUP_INFO_WAS_TRIMMED_BIT 1
62 +#define EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT 2
63 +#define EXT4_GROUP_INFO_BBITMAP_CORRUPT \
64 + (1 << EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT)
65 +#define EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT 3
66 +#define EXT4_GROUP_INFO_IBITMAP_CORRUPT \
67 + (1 << EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT)
69 #define EXT4_MB_GRP_NEED_INIT(grp) \
70 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
71 +#define EXT4_MB_GRP_BBITMAP_CORRUPT(grp) \
72 + (test_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
73 +#define EXT4_MB_GRP_IBITMAP_CORRUPT(grp) \
74 + (test_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
76 #define EXT4_MB_GRP_WAS_TRIMMED(grp) \
77 (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
78 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
79 index 532dcaa..6082e54 100644
80 --- a/fs/ext4/ialloc.c
81 +++ b/fs/ext4/ialloc.c
82 @@ -78,11 +78,10 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
83 /* If checksum is bad mark all blocks and inodes use to prevent
84 * allocation, essentially implementing a per-group read-only flag. */
85 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
86 - ext4_error(sb, "Checksum bad for group %u", block_group);
87 - ext4_free_blks_set(sb, gdp, 0);
88 - ext4_free_inodes_set(sb, gdp, 0);
89 - ext4_itable_unused_set(sb, gdp, 0);
90 - memset(bh->b_data, 0xff, sb->s_blocksize);
91 + ext4_corrupted_block_group(sb, block_group,
92 + EXT4_GROUP_INFO_BBITMAP_CORRUPT |
93 + EXT4_GROUP_INFO_IBITMAP_CORRUPT,
94 + "Checksum bad for group %u", block_group);
98 @@ -195,6 +194,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
99 struct ext4_super_block *es;
100 struct ext4_sb_info *sbi;
101 int fatal = 0, err, count, cleared;
102 + struct ext4_group_info *grp;
104 if (atomic_read(&inode->i_count) > 1) {
105 printk(KERN_ERR "ext4_free_inode: inode has count=%d\n",
106 @@ -238,7 +238,9 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
107 block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
108 bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
109 bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
111 + /* Don't bother if the inode bitmap is corrupt. */
112 + grp = ext4_get_group_info(sb, block_group);
113 + if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || !bitmap_bh)
116 BUFFER_TRACE(bitmap_bh, "get_write_access");
117 @@ -286,8 +288,12 @@ out:
120 ext4_mark_super_dirty(sb);
122 - ext4_error(sb, "bit already cleared for inode %lu", ino);
124 + ext4_corrupted_block_group(sb, block_group,
125 + EXT4_GROUP_INFO_IBITMAP_CORRUPT,
126 + "bit already cleared for inode %lu",
132 @@ -820,6 +826,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
135 ext4_group_t flex_group;
136 + struct ext4_group_info *grp;
138 /* Cannot create files in a deleted directory */
139 if (!dir || !dir->i_nlink)
140 @@ -879,10 +886,21 @@ got_group:
144 + grp = ext4_get_group_info(sb, group);
145 + /* Skip groups with already-known suspicious inode tables */
146 + if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
147 + if (++group == ngroups)
151 brelse(inode_bitmap_bh);
152 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
153 - if (!inode_bitmap_bh)
155 + /* Skip groups with suspicious inode tables */
156 + if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || !inode_bitmap_bh) {
157 + if (++group == ngroups)
162 repeat_in_this_group:
163 ino = ext4_find_next_zero_bit((unsigned long *)
164 diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
165 index 1d77581..4d6558e 100644
166 --- a/fs/ext4/mballoc.c
167 +++ b/fs/ext4/mballoc.c
168 @@ -740,7 +740,6 @@ int ext4_mb_generate_buddy(struct super_block *sb,
169 "%u blocks in bitmap, %u in bb, %u in gd",
171 ext4_free_blks_count(sb, gdp));
174 * If we intent to continue, we consider group descritor
175 * corrupt and update bb_free using bitmap value
176 @@ -1124,7 +1123,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
181 + struct page *page = NULL;
183 struct ext4_group_info *grp;
184 struct ext4_sb_info *sbi = EXT4_SB(sb);
185 @@ -1149,7 +1148,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
187 ret = ext4_mb_init_group(sb, group);
194 @@ -1233,6 +1232,8 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
198 + ext4_warning(sb, "Error in loading buddy information for %u",
201 page_cache_release(page);
202 if (e4b->bd_bitmap_page)
203 @@ -1322,6 +1323,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
205 BUG_ON(first + count > (sb->s_blocksize << 3));
206 assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
207 + /* Don't bother if the block group is corrupt. */
208 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
212 mb_free_blocks_double(inode, e4b, first, count);
214 @@ -1729,6 +1734,11 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
218 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) {
219 + ext4_mb_unload_buddy(e4b);
223 ext4_lock_group(ac->ac_sb, group);
224 max = mb_find_extent(e4b, 0, ac->ac_g_ex.fe_start,
225 ac->ac_g_ex.fe_len, &ex);
226 @@ -1940,6 +1950,9 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
228 BUG_ON(cr < 0 || cr >= 4);
230 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
233 /* We only do this if the grp has never been initialized */
234 if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
235 int ret = ext4_mb_init_group(ac->ac_sb, group);
236 @@ -3458,9 +3471,11 @@ int ext4_mb_check_ondisk_bitmap(struct super_block *sb, void *bitmap,
239 if (free != ext4_free_blks_count(sb, gdp)) {
240 - ext4_error(sb, "on-disk bitmap for group %d"
241 - "corrupted: %u blocks free in bitmap, %u - in gd\n",
242 - group, free, ext4_free_blks_count(sb, gdp));
243 + ext4_corrupted_block_group(sb, group,
244 + EXT4_GROUP_INFO_BBITMAP_CORRUPT,
245 + "on-disk bitmap for group %d corrupted: %u blocks free in bitmap, %u - in gd\n",
247 + ext4_free_blks_count(sb, gdp));
251 @@ -3813,17 +3828,9 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
252 /* "free < pa->pa_free" means we maybe double alloc the same blocks,
253 * otherwise maybe leave some free blocks unavailable, no need to BUG.*/
254 if ((free > pa->pa_free && !pa->pa_error) || (free < pa->pa_free)) {
255 - ext4_error(sb, "pa free mismatch: [pa %p] "
256 - "[phy %lu] [logic %lu] [len %u] [free %u] "
257 - "[error %u] [inode %lu] [freed %u]", pa,
258 - (unsigned long)pa->pa_pstart,
259 - (unsigned long)pa->pa_lstart,
260 - (unsigned)pa->pa_len, (unsigned)pa->pa_free,
261 - (unsigned)pa->pa_error, pa->pa_inode->i_ino,
263 ext4_grp_locked_error(sb, group, 0, 0,
264 - "free %u, pa_free %u",
265 - free, pa->pa_free);
266 + "free %u, pa_free %u",
267 + free, pa->pa_free);
269 * pa is already deleted so we use the value obtained
270 * from the bitmap and continue.
271 @@ -3883,14 +3890,11 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
274 bitmap_bh = ext4_read_block_bitmap(sb, group);
275 - if (bitmap_bh == NULL) {
276 - ext4_error(sb, "Error reading block bitmap for %u", group);
277 + if (bitmap_bh == NULL)
281 err = ext4_mb_load_buddy(sb, group, &e4b);
283 - ext4_error(sb, "Error loading buddy information for %u", group);
287 @@ -4054,16 +4058,11 @@ repeat:
288 ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
290 err = ext4_mb_load_buddy(sb, group, &e4b);
292 - ext4_error(sb, "Error loading buddy information for %u",
298 bitmap_bh = ext4_read_block_bitmap(sb, group);
299 if (bitmap_bh == NULL) {
300 - ext4_error(sb, "Error reading block bitmap for %u",
302 ext4_mb_unload_buddy(&e4b);
305 @@ -4324,11 +4323,8 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
306 list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) {
308 ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
309 - if (ext4_mb_load_buddy(sb, group, &e4b)) {
310 - ext4_error(sb, "Error loading buddy information for %u",
312 + if (ext4_mb_load_buddy(sb, group, &e4b))
315 ext4_lock_group(sb, group);
316 list_del(&pa->pa_group_list);
317 ext4_get_group_info(sb, group)->bb_prealloc_nr--;
318 @@ -4585,7 +4581,7 @@ repeat:
319 * been updated or not when fail case. So can
320 * not revert pa_free back, just mark pa_error*/
323 + ext4_corrupted_block_group(sb, 0, 0,
324 "Updating bitmap error: [err %d] "
325 "[pa %p] [phy %lu] [logic %lu] "
326 "[len %u] [free %u] [error %u] "
327 @@ -4731,6 +4727,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
328 struct ext4_buddy e4b;
331 + int skip_error = 0;
335 @@ -4781,6 +4778,10 @@ do_more:
337 ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
339 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(
340 + ext4_get_group_info(sb, block_group))))
344 * Check to see if we are freeing blocks across a group
346 @@ -4837,8 +4838,10 @@ do_more:
347 trace_ext4_mballoc_free(sb, inode, block_group, bit, count);
349 err = ext4_mb_load_buddy(sb, block_group, &e4b);
356 if ((flags & EXT4_FREE_BLOCKS_METADATA) && ext4_handle_valid(handle)) {
357 struct ext4_free_data *new_entry;
358 @@ -4905,8 +4908,9 @@ do_more:
360 if (freed && !(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
361 dquot_free_block(inode, freed);
363 + ext4_std_error(sb, err);
365 - ext4_std_error(sb, err);
369 @@ -4991,7 +4995,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
371 err = ext4_mb_load_buddy(sb, block_group, &e4b);
377 * need to update group_info->bb_free and bitmap
378 @@ -5026,8 +5030,9 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
383 ext4_std_error(sb, err);
389 @@ -5094,11 +5099,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
392 ret = ext4_mb_load_buddy(sb, group, &e4b);
394 - ext4_error(sb, "Error in loading buddy "
395 - "information for %u", group);
399 bitmap = e4b.bd_bitmap;
401 ext4_lock_group(sb, group);
402 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
403 index a21e903..2fca810 100644
404 --- a/fs/ext4/super.c
405 +++ b/fs/ext4/super.c
406 @@ -666,6 +666,32 @@ void __ext4_warning(struct super_block *sb, const char *function,
410 +void __ext4_corrupted_block_group(struct super_block *sb, ext4_group_t group,
411 + unsigned int flags, const char *function,
414 + struct ext4_group_info *grp = ext4_get_group_info(sb, group);
415 + struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
417 + if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT &&
418 + !EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) {
419 + ext4_free_blks_set(sb, gdp, 0);
420 + set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
424 + if (flags & EXT4_GROUP_INFO_IBITMAP_CORRUPT &&
425 + !EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
427 + ext4_free_inodes_set(sb, gdp, 0);
428 + ext4_itable_unused_set(sb, gdp, 0);
430 + set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT,
433 + save_error_info(sb, function, line);
436 void __ext4_grp_locked_error(const char *function, unsigned int line,
437 struct super_block *sb, ext4_group_t grp,
438 unsigned long ino, ext4_fsblk_t block,