aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorDaeho Jeong <daeho.jeong@samsung.com>2015-10-18 17:02:56 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-10-18 17:02:56 -0400
commit4327ba52afd03fc4b5afa0ee1d774c9c5b0e85c5 (patch)
tree586491d92df3043ec5ddd0beaa92bd7cda77ae3d /fs/ext4
parent904dad4742d211b7a8910e92695c0fa957483836 (diff)
ext4, jbd2: ensure entering into panic after recording an error in superblock
If a EXT4 filesystem utilizes JBD2 journaling and an error occurs, the journaling will be aborted first and the error number will be recorded into JBD2 superblock and, finally, the system will enter into the panic state in "errors=panic" option. But, in the rare case, this sequence is little twisted like the below figure and it will happen that the system enters into panic state, which means the system reset in mobile environment, before completion of recording an error in the journal superblock. In this case, e2fsck cannot recognize that the filesystem failure occurred in the previous run and the corruption wouldn't be fixed. Task A Task B ext4_handle_error() -> jbd2_journal_abort() -> __journal_abort_soft() -> __jbd2_journal_abort_hard() | -> journal->j_flags |= JBD2_ABORT; | | __ext4_abort() | -> jbd2_journal_abort() | | -> __journal_abort_soft() | | -> if (journal->j_flags & JBD2_ABORT) | | return; | -> panic() | -> jbd2_journal_update_sb_errno() Tested-by: Hobin Woo <hobin.woo@samsung.com> Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@vger.kernel.org
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/super.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 49fa4d48b6a4..639613fe20aa 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -388,9 +388,13 @@ static void ext4_handle_error(struct super_block *sb)
388 smp_wmb(); 388 smp_wmb();
389 sb->s_flags |= MS_RDONLY; 389 sb->s_flags |= MS_RDONLY;
390 } 390 }
391 if (test_opt(sb, ERRORS_PANIC)) 391 if (test_opt(sb, ERRORS_PANIC)) {
392 if (EXT4_SB(sb)->s_journal &&
393 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
394 return;
392 panic("EXT4-fs (device %s): panic forced after error\n", 395 panic("EXT4-fs (device %s): panic forced after error\n",
393 sb->s_id); 396 sb->s_id);
397 }
394} 398}
395 399
396#define ext4_error_ratelimit(sb) \ 400#define ext4_error_ratelimit(sb) \
@@ -585,8 +589,12 @@ void __ext4_abort(struct super_block *sb, const char *function,
585 jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); 589 jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
586 save_error_info(sb, function, line); 590 save_error_info(sb, function, line);
587 } 591 }
588 if (test_opt(sb, ERRORS_PANIC)) 592 if (test_opt(sb, ERRORS_PANIC)) {
593 if (EXT4_SB(sb)->s_journal &&
594 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
595 return;
589 panic("EXT4-fs panic from previous error\n"); 596 panic("EXT4-fs panic from previous error\n");
597 }
590} 598}
591 599
592void __ext4_msg(struct super_block *sb, 600void __ext4_msg(struct super_block *sb,