ext4: pass -ESHUTDOWN code to jbd2 layer
authorTheodore Ts'o <tytso@mit.edu>
Mon, 19 Feb 2018 04:45:18 +0000 (23:45 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 19 Feb 2018 04:45:18 +0000 (23:45 -0500)
Previously the jbd2 layer assumed that a file system check would be
required after a journal abort.  In the case of the deliberate file
system shutdown, this should not be necessary.  Allow the jbd2 layer
to distinguish between these two cases by using the ESHUTDOWN errno.

Also add proper locking to __journal_abort_soft().

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
fs/ext4/ioctl.c
fs/jbd2/journal.c

index 16d3d1325f5bb017db004b52018066c8ba7977aa..9ac33a7cbd321ad7dce50d0fe18dffeea03190e0 100644 (file)
@@ -493,13 +493,13 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg)
                set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
                if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
                        (void) ext4_force_commit(sb);
-                       jbd2_journal_abort(sbi->s_journal, 0);
+                       jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
                }
                break;
        case EXT4_GOING_FLAGS_NOLOGFLUSH:
                set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
                if (sbi->s_journal && !is_journal_aborted(sbi->s_journal))
-                       jbd2_journal_abort(sbi->s_journal, 0);
+                       jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
                break;
        default:
                return -EINVAL;
index 3fbf48ec21881698325f3b84c4b2654485d7711b..efa0c72a0b9f13abd8ede4a3b66a9db19c9a1410 100644 (file)
@@ -1483,12 +1483,15 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
 void jbd2_journal_update_sb_errno(journal_t *journal)
 {
        journal_superblock_t *sb = journal->j_superblock;
+       int errcode;
 
        read_lock(&journal->j_state_lock);
-       jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
-                 journal->j_errno);
-       sb->s_errno    = cpu_to_be32(journal->j_errno);
+       errcode = journal->j_errno;
        read_unlock(&journal->j_state_lock);
+       if (errcode == -ESHUTDOWN)
+               errcode = 0;
+       jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
+       sb->s_errno    = cpu_to_be32(errcode);
 
        jbd2_write_superblock(journal, REQ_SYNC | REQ_FUA);
 }
@@ -2105,12 +2108,22 @@ void __jbd2_journal_abort_hard(journal_t *journal)
  * but don't do any other IO. */
 static void __journal_abort_soft (journal_t *journal, int errno)
 {
-       if (journal->j_flags & JBD2_ABORT)
-               return;
+       int old_errno;
 
-       if (!journal->j_errno)
+       write_lock(&journal->j_state_lock);
+       old_errno = journal->j_errno;
+       if (!journal->j_errno || errno == -ESHUTDOWN)
                journal->j_errno = errno;
 
+       if (journal->j_flags & JBD2_ABORT) {
+               write_unlock(&journal->j_state_lock);
+               if (!old_errno && old_errno != -ESHUTDOWN &&
+                   errno == -ESHUTDOWN)
+                       jbd2_journal_update_sb_errno(journal);
+               return;
+       }
+       write_unlock(&journal->j_state_lock);
+
        __jbd2_journal_abort_hard(journal);
 
        if (errno) {