Update fixes for making ext4 more robust against malicious images
[ext4-patch-queue.git] / use-shutdown-errcode
blob7afb056f8fbcb240cdde31ddec55de58db0dbb2d
1 ext4: pass -ESHUTDOWN code to jbd2 layer
3 Previously the jbd2 layer assumed that a file system check would be
4 required after a journal abort.  In the case of the deliberate file
5 system shutdown, this should not be necessary.  Allow the jbd2 layer
6 to distinguish between these two cases by using the ESHUTDOWN errno.
8 Also add proper locking to __journal_abort_soft().
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
11 Cc: stable@vger.kernel.org
12 ---
13  fs/ext4/ioctl.c   |  4 ++--
14  fs/jbd2/journal.c | 25 +++++++++++++++++++------
15  2 files changed, 21 insertions(+), 8 deletions(-)
17 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
18 index 16d3d1325f5b..9ac33a7cbd32 100644
19 --- a/fs/ext4/ioctl.c
20 +++ b/fs/ext4/ioctl.c
21 @@ -493,13 +493,13 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg)
22                 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
23                 if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
24                         (void) ext4_force_commit(sb);
25 -                       jbd2_journal_abort(sbi->s_journal, 0);
26 +                       jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
27                 }
28                 break;
29         case EXT4_GOING_FLAGS_NOLOGFLUSH:
30                 set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
31                 if (sbi->s_journal && !is_journal_aborted(sbi->s_journal))
32 -                       jbd2_journal_abort(sbi->s_journal, 0);
33 +                       jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
34                 break;
35         default:
36                 return -EINVAL;
37 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
38 index 3fbf48ec2188..efa0c72a0b9f 100644
39 --- a/fs/jbd2/journal.c
40 +++ b/fs/jbd2/journal.c
41 @@ -1483,12 +1483,15 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
42  void jbd2_journal_update_sb_errno(journal_t *journal)
43  {
44         journal_superblock_t *sb = journal->j_superblock;
45 +       int errcode;
47         read_lock(&journal->j_state_lock);
48 -       jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
49 -                 journal->j_errno);
50 -       sb->s_errno    = cpu_to_be32(journal->j_errno);
51 +       errcode = journal->j_errno;
52         read_unlock(&journal->j_state_lock);
53 +       if (errcode == -ESHUTDOWN)
54 +               errcode = 0;
55 +       jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
56 +       sb->s_errno    = cpu_to_be32(errcode);
58         jbd2_write_superblock(journal, REQ_SYNC | REQ_FUA);
59  }
60 @@ -2105,12 +2108,22 @@ void __jbd2_journal_abort_hard(journal_t *journal)
61   * but don't do any other IO. */
62  static void __journal_abort_soft (journal_t *journal, int errno)
63  {
64 -       if (journal->j_flags & JBD2_ABORT)
65 -               return;
66 +       int old_errno;
68 -       if (!journal->j_errno)
69 +       write_lock(&journal->j_state_lock);
70 +       old_errno = journal->j_errno;
71 +       if (!journal->j_errno || errno == -ESHUTDOWN)
72                 journal->j_errno = errno;
74 +       if (journal->j_flags & JBD2_ABORT) {
75 +               write_unlock(&journal->j_state_lock);
76 +               if (!old_errno && old_errno != -ESHUTDOWN &&
77 +                   errno == -ESHUTDOWN)
78 +                       jbd2_journal_update_sb_errno(journal);
79 +               return;
80 +       }
81 +       write_unlock(&journal->j_state_lock);
83         __jbd2_journal_abort_hard(journal);
85         if (errno) {