aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/ialloc.c29
2 files changed, 28 insertions, 4 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 02b764b4e635..06b488dca666 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2481,11 +2481,14 @@ struct ext4_group_info {
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#define EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT 2
2484#define EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT 3
2484 2485
2485#define EXT4_MB_GRP_NEED_INIT(grp) \ 2486#define EXT4_MB_GRP_NEED_INIT(grp) \
2486 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state))) 2487 (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
2487#define EXT4_MB_GRP_BBITMAP_CORRUPT(grp) \ 2488#define EXT4_MB_GRP_BBITMAP_CORRUPT(grp) \
2488 (test_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &((grp)->bb_state))) 2489 (test_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
2490#define EXT4_MB_GRP_IBITMAP_CORRUPT(grp) \
2491 (test_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &((grp)->bb_state)))
2489 2492
2490#define EXT4_MB_GRP_WAS_TRIMMED(grp) \ 2493#define EXT4_MB_GRP_WAS_TRIMMED(grp) \
2491 (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state))) 2494 (test_bit(EXT4_GROUP_INFO_WAS_TRIMMED_BIT, &((grp)->bb_state)))
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 666a5ed48bcc..d5106078595e 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -117,6 +117,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
117 struct ext4_group_desc *desc; 117 struct ext4_group_desc *desc;
118 struct buffer_head *bh = NULL; 118 struct buffer_head *bh = NULL;
119 ext4_fsblk_t bitmap_blk; 119 ext4_fsblk_t bitmap_blk;
120 struct ext4_group_info *grp;
120 121
121 desc = ext4_get_group_desc(sb, block_group, NULL); 122 desc = ext4_get_group_desc(sb, block_group, NULL);
122 if (!desc) 123 if (!desc)
@@ -185,6 +186,8 @@ verify:
185 put_bh(bh); 186 put_bh(bh);
186 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, " 187 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "
187 "inode_bitmap = %llu", block_group, bitmap_blk); 188 "inode_bitmap = %llu", block_group, bitmap_blk);
189 grp = ext4_get_group_info(sb, block_group);
190 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
188 return NULL; 191 return NULL;
189 } 192 }
190 ext4_unlock_group(sb, block_group); 193 ext4_unlock_group(sb, block_group);
@@ -221,6 +224,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
221 struct ext4_super_block *es; 224 struct ext4_super_block *es;
222 struct ext4_sb_info *sbi; 225 struct ext4_sb_info *sbi;
223 int fatal = 0, err, count, cleared; 226 int fatal = 0, err, count, cleared;
227 struct ext4_group_info *grp;
224 228
225 if (!sb) { 229 if (!sb) {
226 printk(KERN_ERR "EXT4-fs: %s:%d: inode on " 230 printk(KERN_ERR "EXT4-fs: %s:%d: inode on "
@@ -266,7 +270,9 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
266 block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); 270 block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
267 bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); 271 bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
268 bitmap_bh = ext4_read_inode_bitmap(sb, block_group); 272 bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
269 if (!bitmap_bh) 273 /* Don't bother if the inode bitmap is corrupt. */
274 grp = ext4_get_group_info(sb, block_group);
275 if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || !bitmap_bh)
270 goto error_return; 276 goto error_return;
271 277
272 BUFFER_TRACE(bitmap_bh, "get_write_access"); 278 BUFFER_TRACE(bitmap_bh, "get_write_access");
@@ -315,8 +321,10 @@ out:
315 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); 321 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
316 if (!fatal) 322 if (!fatal)
317 fatal = err; 323 fatal = err;
318 } else 324 } else {
319 ext4_error(sb, "bit already cleared for inode %lu", ino); 325 ext4_error(sb, "bit already cleared for inode %lu", ino);
326 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
327 }
320 328
321error_return: 329error_return:
322 brelse(bitmap_bh); 330 brelse(bitmap_bh);
@@ -697,6 +705,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
697 struct inode *ret; 705 struct inode *ret;
698 ext4_group_t i; 706 ext4_group_t i;
699 ext4_group_t flex_group; 707 ext4_group_t flex_group;
708 struct ext4_group_info *grp;
700 709
701 /* Cannot create files in a deleted directory */ 710 /* Cannot create files in a deleted directory */
702 if (!dir || !dir->i_nlink) 711 if (!dir || !dir->i_nlink)
@@ -770,10 +779,22 @@ got_group:
770 continue; 779 continue;
771 } 780 }
772 781
782 grp = ext4_get_group_info(sb, group);
783 /* Skip groups with already-known suspicious inode tables */
784 if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
785 if (++group == ngroups)
786 group = 0;
787 continue;
788 }
789
773 brelse(inode_bitmap_bh); 790 brelse(inode_bitmap_bh);
774 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); 791 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
775 if (!inode_bitmap_bh) 792 /* Skip groups with suspicious inode tables */
776 goto out; 793 if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || !inode_bitmap_bh) {
794 if (++group == ngroups)
795 group = 0;
796 continue;
797 }
777 798
778repeat_in_this_group: 799repeat_in_this_group:
779 ino = ext4_find_next_zero_bit((unsigned long *) 800 ino = ext4_find_next_zero_bit((unsigned long *)