diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-17 11:04:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-17 11:04:47 -0400 |
commit | ef824bfba2cce6a75c7cd740f6ad80581e75a109 (patch) | |
tree | 10cdb7ae50f4c8a9a16e55a62bce245f1924889f /fs | |
parent | d807ff838f48e7778996e577e2a57a5796c32e84 (diff) | |
parent | 89a4e48f8479f8145eca9698f39fe188c982212f (diff) |
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bug fixes from Ted Ts'o:
"The following are all bug fixes and regressions. The most notable are
the ones which cause problems for ext4 on RAID --- a performance
problem when mounting very large filesystems, and a kernel OOPS when
doing an rm -rf on large directory hierarchies on fast devices."
* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix kernel BUG on large-scale rm -rf commands
ext4: fix long mount times on very big file systems
ext4: don't call ext4_error while block group is locked
ext4: avoid kmemcheck complaint from reading uninitialized memory
ext4: make sure the journal sb is written in ext4_clear_journal_err()
Diffstat (limited to 'fs')
-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 |
5 files changed, 46 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 |