aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-17 11:04:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-17 11:04:47 -0400
commitef824bfba2cce6a75c7cd740f6ad80581e75a109 (patch)
tree10cdb7ae50f4c8a9a16e55a62bce245f1924889f /fs
parentd807ff838f48e7778996e577e2a57a5796c32e84 (diff)
parent89a4e48f8479f8145eca9698f39fe188c982212f (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.c62
-rw-r--r--fs/ext4/bitmap.c1
-rw-r--r--fs/ext4/extents.c1
-rw-r--r--fs/ext4/super.c6
-rw-r--r--fs/jbd2/journal.c3
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
283static 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 */
287static 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
328err_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 */
1380static void jbd2_journal_update_sb_errno(journal_t *journal) 1380void 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}
1393EXPORT_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