]> git.hungrycats.org Git - linux/commitdiff
ext4: make sure the journal sb is written in ext4_clear_journal_err()
authorTheodore Ts'o <tytso@mit.edu>
Sun, 5 Aug 2012 23:04:57 +0000 (19:04 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 26 Aug 2012 22:00:42 +0000 (15:00 -0700)
commit d796c52ef0b71a988364f6109aeb63d79c5b116b upstream.

After we transfer set the EXT4_ERROR_FS bit in the file system
superblock, it's not enough to call jbd2_journal_clear_err() to clear
the error indication from journal superblock --- we need to call
jbd2_journal_update_sb_errno() as well.  Otherwise, when the root file
system is mounted read-only, the journal is replayed, and the error
indicator is transferred to the superblock --- but the s_errno field
in the jbd2 superblock is left set (since although we cleared it in
memory, we never flushed it out to disk).

This can end up confusing e2fsck.  We should make e2fsck more robust
in this case, but the kernel shouldn't be leaving things in this
confused state, either.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ext4/super.c
fs/jbd2/journal.c
include/linux/jbd2.h

index 7fe3869d33d514a858109ab063e945899bfa71c5..78fb7ff3adb8b40315e7b30326efe771c0cebe15 100644 (file)
@@ -4227,6 +4227,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
                ext4_commit_super(sb, 1);
 
                jbd2_journal_clear_err(journal);
+               jbd2_journal_update_sb_errno(journal);
        }
 }
 
index 1afb701622b0b17748b4cd7f7d171df139bcc9cc..9956ac68b72bdc7abc44564f8c5dc8771276dc24 100644 (file)
@@ -1340,7 +1340,7 @@ static void jbd2_mark_journal_empty(journal_t *journal)
  * Update a journal's errno.  Write updated superblock to disk waiting for IO
  * to complete.
  */
-static void jbd2_journal_update_sb_errno(journal_t *journal)
+void jbd2_journal_update_sb_errno(journal_t *journal)
 {
        journal_superblock_t *sb = journal->j_superblock;
 
@@ -1352,6 +1352,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)
 
        jbd2_write_superblock(journal, WRITE_SYNC);
 }
+EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
 
 /*
  * Read the superblock for a given journal, performing initial
index 912c30a8ddb1e47cd732fbd95f281238ca601ae0..2ed66ef2e68b72f287b5ac21985191cf42a51833 100644 (file)
@@ -1091,6 +1091,7 @@ extern int           jbd2_journal_destroy    (journal_t *);
 extern int        jbd2_journal_recover    (journal_t *journal);
 extern int        jbd2_journal_wipe       (journal_t *, int);
 extern int        jbd2_journal_skip_recovery   (journal_t *);
+extern void       jbd2_journal_update_sb_errno(journal_t *);
 extern void       jbd2_journal_update_sb_log_tail      (journal_t *, tid_t,
                                unsigned long, int);
 extern void       __jbd2_journal_abort_hard    (journal_t *);