diff options
| -rw-r--r-- | fs/ext4/balloc.c | 62 | ||||
| -rw-r--r-- | fs/ext4/bitmap.c | 1 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 1 | ||||
| -rw-r--r-- | fs/ext4/super.c | 6 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 3 | ||||
| -rw-r--r-- | include/linux/jbd2.h | 1 |
6 files changed, 47 insertions, 27 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index d23b31ca9d7a..1b5089067d01 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -280,14 +280,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, | |||
| 280 | return desc; | 280 | return desc; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static int ext4_valid_block_bitmap(struct super_block *sb, | 283 | /* |
| 284 | struct ext4_group_desc *desc, | 284 | * Return the block number which was discovered to be invalid, or 0 if |
| 285 | unsigned int block_group, | 285 | * the block bitmap is valid. |
| 286 | struct buffer_head *bh) | 286 | */ |
| 287 | static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, | ||
| 288 | struct ext4_group_desc *desc, | ||
| 289 | unsigned int block_group, | ||
| 290 | struct buffer_head *bh) | ||
| 287 | { | 291 | { |
| 288 | ext4_grpblk_t offset; | 292 | ext4_grpblk_t offset; |
| 289 | ext4_grpblk_t next_zero_bit; | 293 | ext4_grpblk_t next_zero_bit; |
| 290 | ext4_fsblk_t bitmap_blk; | 294 | ext4_fsblk_t blk; |
| 291 | ext4_fsblk_t group_first_block; | 295 | ext4_fsblk_t group_first_block; |
| 292 | 296 | ||
| 293 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { | 297 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { |
| @@ -297,37 +301,33 @@ static int ext4_valid_block_bitmap(struct super_block *sb, | |||
| 297 | * or it has to also read the block group where the bitmaps | 301 | * or it has to also read the block group where the bitmaps |
| 298 | * are located to verify they are set. | 302 | * are located to verify they are set. |
| 299 | */ | 303 | */ |
| 300 | return 1; | 304 | return 0; |
| 301 | } | 305 | } |
| 302 | group_first_block = ext4_group_first_block_no(sb, block_group); | 306 | group_first_block = ext4_group_first_block_no(sb, block_group); |
| 303 | 307 | ||
| 304 | /* check whether block bitmap block number is set */ | 308 | /* check whether block bitmap block number is set */ |
| 305 | bitmap_blk = ext4_block_bitmap(sb, desc); | 309 | blk = ext4_block_bitmap(sb, desc); |
| 306 | offset = bitmap_blk - group_first_block; | 310 | offset = blk - group_first_block; |
| 307 | if (!ext4_test_bit(offset, bh->b_data)) | 311 | if (!ext4_test_bit(offset, bh->b_data)) |
| 308 | /* bad block bitmap */ | 312 | /* bad block bitmap */ |
| 309 | goto err_out; | 313 | return blk; |
| 310 | 314 | ||
| 311 | /* check whether the inode bitmap block number is set */ | 315 | /* check whether the inode bitmap block number is set */ |
| 312 | bitmap_blk = ext4_inode_bitmap(sb, desc); | 316 | blk = ext4_inode_bitmap(sb, desc); |
| 313 | offset = bitmap_blk - group_first_block; | 317 | offset = blk - group_first_block; |
| 314 | if (!ext4_test_bit(offset, bh->b_data)) | 318 | if (!ext4_test_bit(offset, bh->b_data)) |
| 315 | /* bad block bitmap */ | 319 | /* bad block bitmap */ |
| 316 | goto err_out; | 320 | return blk; |
| 317 | 321 | ||
| 318 | /* check whether the inode table block number is set */ | 322 | /* check whether the inode table block number is set */ |
| 319 | bitmap_blk = ext4_inode_table(sb, desc); | 323 | blk = ext4_inode_table(sb, desc); |
| 320 | offset = bitmap_blk - group_first_block; | 324 | offset = blk - group_first_block; |
| 321 | next_zero_bit = ext4_find_next_zero_bit(bh->b_data, | 325 | next_zero_bit = ext4_find_next_zero_bit(bh->b_data, |
| 322 | offset + EXT4_SB(sb)->s_itb_per_group, | 326 | offset + EXT4_SB(sb)->s_itb_per_group, |
| 323 | offset); | 327 | offset); |
| 324 | if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) | 328 | if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group) |
| 325 | /* good bitmap for inode tables */ | 329 | /* bad bitmap for inode tables */ |
| 326 | return 1; | 330 | return blk; |
| 327 | |||
| 328 | err_out: | ||
| 329 | ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu", | ||
| 330 | block_group, bitmap_blk); | ||
| 331 | return 0; | 331 | return 0; |
| 332 | } | 332 | } |
| 333 | 333 | ||
| @@ -336,14 +336,26 @@ void ext4_validate_block_bitmap(struct super_block *sb, | |||
| 336 | unsigned int block_group, | 336 | unsigned int block_group, |
| 337 | struct buffer_head *bh) | 337 | struct buffer_head *bh) |
| 338 | { | 338 | { |
| 339 | ext4_fsblk_t blk; | ||
| 340 | |||
| 339 | if (buffer_verified(bh)) | 341 | if (buffer_verified(bh)) |
| 340 | return; | 342 | return; |
| 341 | 343 | ||
| 342 | ext4_lock_group(sb, block_group); | 344 | ext4_lock_group(sb, block_group); |
| 343 | if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && | 345 | blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); |
| 344 | ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, | 346 | if (unlikely(blk != 0)) { |
| 345 | EXT4_BLOCKS_PER_GROUP(sb) / 8)) | 347 | ext4_unlock_group(sb, block_group); |
| 346 | set_buffer_verified(bh); | 348 | ext4_error(sb, "bg %u: block %llu: invalid block bitmap", |
| 349 | block_group, blk); | ||
| 350 | return; | ||
| 351 | } | ||
| 352 | if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, | ||
| 353 | desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { | ||
| 354 | ext4_unlock_group(sb, block_group); | ||
| 355 | ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); | ||
| 356 | return; | ||
| 357 | } | ||
| 358 | set_buffer_verified(bh); | ||
| 347 | ext4_unlock_group(sb, block_group); | 359 | ext4_unlock_group(sb, block_group); |
| 348 | } | 360 | } |
| 349 | 361 | ||
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index f8716eab9995..5c2d1813ebe9 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c | |||
| @@ -79,7 +79,6 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, | |||
| 79 | if (provided == calculated) | 79 | if (provided == calculated) |
| 80 | return 1; | 80 | return 1; |
| 81 | 81 | ||
| 82 | ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group); | ||
| 83 | return 0; | 82 | return 0; |
| 84 | } | 83 | } |
| 85 | 84 | ||
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index cd0c7ed06772..aabbb3f53683 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -2662,6 +2662,7 @@ cont: | |||
| 2662 | } | 2662 | } |
| 2663 | path[0].p_depth = depth; | 2663 | path[0].p_depth = depth; |
| 2664 | path[0].p_hdr = ext_inode_hdr(inode); | 2664 | path[0].p_hdr = ext_inode_hdr(inode); |
| 2665 | i = 0; | ||
| 2665 | 2666 | ||
| 2666 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { | 2667 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { |
| 2667 | err = -EIO; | 2668 | err = -EIO; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3e0851e4f468..c6e0cb3d1f4a 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -948,6 +948,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
| 948 | ei->i_reserved_meta_blocks = 0; | 948 | ei->i_reserved_meta_blocks = 0; |
| 949 | ei->i_allocated_meta_blocks = 0; | 949 | ei->i_allocated_meta_blocks = 0; |
| 950 | ei->i_da_metadata_calc_len = 0; | 950 | ei->i_da_metadata_calc_len = 0; |
| 951 | ei->i_da_metadata_calc_last_lblock = 0; | ||
| 951 | spin_lock_init(&(ei->i_block_reservation_lock)); | 952 | spin_lock_init(&(ei->i_block_reservation_lock)); |
| 952 | #ifdef CONFIG_QUOTA | 953 | #ifdef CONFIG_QUOTA |
| 953 | ei->i_reserved_quota = 0; | 954 | ei->i_reserved_quota = 0; |
| @@ -3108,6 +3109,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp, | |||
| 3108 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); | 3109 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); |
| 3109 | int s, j, count = 0; | 3110 | int s, j, count = 0; |
| 3110 | 3111 | ||
| 3112 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) | ||
| 3113 | return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + | ||
| 3114 | sbi->s_itb_per_group + 2); | ||
| 3115 | |||
| 3111 | first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + | 3116 | first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + |
| 3112 | (grp * EXT4_BLOCKS_PER_GROUP(sb)); | 3117 | (grp * EXT4_BLOCKS_PER_GROUP(sb)); |
| 3113 | last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; | 3118 | last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; |
| @@ -4419,6 +4424,7 @@ static void ext4_clear_journal_err(struct super_block *sb, | |||
| 4419 | ext4_commit_super(sb, 1); | 4424 | ext4_commit_super(sb, 1); |
| 4420 | 4425 | ||
| 4421 | jbd2_journal_clear_err(journal); | 4426 | jbd2_journal_clear_err(journal); |
| 4427 | jbd2_journal_update_sb_errno(journal); | ||
| 4422 | } | 4428 | } |
| 4423 | } | 4429 | } |
| 4424 | 4430 | ||
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 8625da27eccf..e149b99a7ffb 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal) | |||
| 1377 | * Update a journal's errno. Write updated superblock to disk waiting for IO | 1377 | * Update a journal's errno. Write updated superblock to disk waiting for IO |
| 1378 | * to complete. | 1378 | * to complete. |
| 1379 | */ | 1379 | */ |
| 1380 | static void jbd2_journal_update_sb_errno(journal_t *journal) | 1380 | void jbd2_journal_update_sb_errno(journal_t *journal) |
| 1381 | { | 1381 | { |
| 1382 | journal_superblock_t *sb = journal->j_superblock; | 1382 | journal_superblock_t *sb = journal->j_superblock; |
| 1383 | 1383 | ||
| @@ -1390,6 +1390,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) | |||
| 1390 | 1390 | ||
| 1391 | jbd2_write_superblock(journal, WRITE_SYNC); | 1391 | jbd2_write_superblock(journal, WRITE_SYNC); |
| 1392 | } | 1392 | } |
| 1393 | EXPORT_SYMBOL(jbd2_journal_update_sb_errno); | ||
| 1393 | 1394 | ||
| 1394 | /* | 1395 | /* |
| 1395 | * Read the superblock for a given journal, performing initial | 1396 | * Read the superblock for a given journal, performing initial |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index f334c7fab967..3efc43f3f162 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
| @@ -1125,6 +1125,7 @@ extern int jbd2_journal_destroy (journal_t *); | |||
| 1125 | extern int jbd2_journal_recover (journal_t *journal); | 1125 | extern int jbd2_journal_recover (journal_t *journal); |
| 1126 | extern int jbd2_journal_wipe (journal_t *, int); | 1126 | extern int jbd2_journal_wipe (journal_t *, int); |
| 1127 | extern int jbd2_journal_skip_recovery (journal_t *); | 1127 | extern int jbd2_journal_skip_recovery (journal_t *); |
| 1128 | extern void jbd2_journal_update_sb_errno(journal_t *); | ||
| 1128 | extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, | 1129 | extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, |
| 1129 | unsigned long, int); | 1130 | unsigned long, int); |
| 1130 | extern void __jbd2_journal_abort_hard (journal_t *); | 1131 | extern void __jbd2_journal_abort_hard (journal_t *); |
