add patch fix-potential-use-after-free-after-remounting-with-noblock_validity
[ext4-patch-queue.git] / add-journal-no-cleanup-option
blob2d04fecf77cd9d7a719b25c8e1dd0fc78219eaba
1 ext4, jbd2: add the journal_nocleanup mount option
3 This debugging option is useful for generating test cases for the
4 journal replay code.
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
7 ---
8  fs/ext4/ext4.h       |  1 +
9  fs/ext4/super.c      | 11 ++++++++++-
10  fs/jbd2/journal.c    | 12 +++++++++---
11  include/linux/jbd2.h |  1 +
12  4 files changed, 21 insertions(+), 4 deletions(-)
14 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
15 index 7c7123f265c2..fc2bdaa71c44 100644
16 --- a/fs/ext4/ext4.h
17 +++ b/fs/ext4/ext4.h
18 @@ -1115,6 +1115,7 @@ struct ext4_inode_info {
19  #define EXT4_MOUNT_JOURNAL_CHECKSUM    0x800000 /* Journal checksums */
20  #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT        0x1000000 /* Journal Async Commit */
21  #define EXT4_MOUNT_WARN_ON_ERROR       0x2000000 /* Trigger WARN_ON on error */
22 +#define EXT4_MOUNT_JOURNAL_NOCLEANUP   0x4000000 /* Preserve the journal on unmount */
23  #define EXT4_MOUNT_DELALLOC            0x8000000 /* Delalloc support */
24  #define EXT4_MOUNT_DATA_ERR_ABORT      0x10000000 /* Abort on file data write */
25  #define EXT4_MOUNT_BLOCK_VALIDITY      0x20000000 /* Block validity checking */
26 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
27 index ae86983cbf60..9339717b85c8 100644
28 --- a/fs/ext4/super.c
29 +++ b/fs/ext4/super.c
30 @@ -928,7 +928,7 @@ static void ext4_put_super(struct super_block *sb)
31         ext4_mb_release(sb);
32         ext4_ext_release(sb);
34 -       if (!sb_rdonly(sb) && !aborted) {
35 +       if (!sb_rdonly(sb) && !aborted && !test_opt(sb, JOURNAL_NOCLEANUP)) {
36                 ext4_clear_feature_journal_needs_recovery(sb);
37                 es->s_state = cpu_to_le16(sbi->s_mount_state);
38         }
39 @@ -1383,6 +1383,7 @@ enum {
40         Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
41         Opt_inode_readahead_blks, Opt_journal_ioprio,
42         Opt_dioread_nolock, Opt_dioread_lock,
43 +       Opt_journal_nocleanup, Opt_journal_cleanup,
44         Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
45         Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
46  };
47 @@ -1471,6 +1472,8 @@ static const match_table_t tokens = {
48         {Opt_test_dummy_encryption, "test_dummy_encryption"},
49         {Opt_nombcache, "nombcache"},
50         {Opt_nombcache, "no_mbcache"},  /* for backward compatibility */
51 +       {Opt_journal_nocleanup, "journal_nocleanup"},
52 +       {Opt_journal_cleanup, "journal_cleanup"},
53         {Opt_removed, "check=none"},    /* mount option from ext2/3 */
54         {Opt_removed, "nocheck"},       /* mount option from ext2/3 */
55         {Opt_removed, "reservation"},   /* mount option from ext2/3 */
56 @@ -1681,6 +1684,8 @@ static const struct mount_opts {
57         {Opt_max_dir_size_kb, 0, MOPT_GTE0},
58         {Opt_test_dummy_encryption, 0, MOPT_GTE0},
59         {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
60 +       {Opt_journal_nocleanup, EXT4_MOUNT_JOURNAL_NOCLEANUP, MOPT_SET},
61 +       {Opt_journal_cleanup, EXT4_MOUNT_JOURNAL_NOCLEANUP, MOPT_CLEAR},
62         {Opt_err, 0, 0}
63  };
65 @@ -4561,6 +4566,10 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
66                 journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR;
67         else
68                 journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR;
69 +       if (test_opt(sb, JOURNAL_NOCLEANUP))
70 +               journal->j_flags |= JBD2_NO_CLEANUP;
71 +       else
72 +               journal->j_flags &= ~JBD2_NO_CLEANUP;
73         write_unlock(&journal->j_state_lock);
74  }
76 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
77 index 8ef6b6daaa7a..860ab3c802a4 100644
78 --- a/fs/jbd2/journal.c
79 +++ b/fs/jbd2/journal.c
80 @@ -1727,6 +1727,11 @@ int jbd2_journal_destroy(journal_t *journal)
81         if (journal->j_running_transaction)
82                 jbd2_journal_commit_transaction(journal);
84 +       if (journal->j_flags & JBD2_NO_CLEANUP) {
85 +               jbd2_journal_destroy_checkpoint(journal);
86 +               journal->j_checkpoint_transactions = NULL;
87 +       }
89         /* Force any old transactions to disk */
91         /* Totally anal locking here... */
92 @@ -1754,7 +1759,9 @@ int jbd2_journal_destroy(journal_t *journal)
93         spin_unlock(&journal->j_list_lock);
95         if (journal->j_sb_buffer) {
96 -               if (!is_journal_aborted(journal)) {
97 +               if (is_journal_aborted(journal))
98 +                       err = -EIO;
99 +               else if ((journal->j_flags & JBD2_NO_CLEANUP) == 0) {
100                         mutex_lock_io(&journal->j_checkpoint_mutex);
102                         write_lock(&journal->j_state_lock);
103 @@ -1765,8 +1772,7 @@ int jbd2_journal_destroy(journal_t *journal)
104                         jbd2_mark_journal_empty(journal,
105                                         REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
106                         mutex_unlock(&journal->j_checkpoint_mutex);
107 -               } else
108 -                       err = -EIO;
109 +               }
110                 brelse(journal->j_sb_buffer);
111         }
113 diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
114 index b708e5169d1d..81fa9fa7ce9c 100644
115 --- a/include/linux/jbd2.h
116 +++ b/include/linux/jbd2.h
117 @@ -1235,6 +1235,7 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum3,                CSUM_V3)
118                                                  * data write error in ordered
119                                                  * mode */
120  #define JBD2_REC_ERR   0x080   /* The errno in the sb has been recorded */
121 +#define JBD2_NO_CLEANUP        0x100   /* Don't flush empty the journal on shutdown  */
123  /*
124   * Function declarations for the journaling transaction and buffer