diff options
| -rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
| -rw-r--r-- | fs/ext4/ialloc.c | 29 |
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 | ||
| 321 | error_return: | 329 | error_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 | ||
| 778 | repeat_in_this_group: | 799 | repeat_in_this_group: |
| 779 | ino = ext4_find_next_zero_bit((unsigned long *) | 800 | ino = ext4_find_next_zero_bit((unsigned long *) |
