jbd2: fix FS corruption possibility in jbd2_journal_destroy() on umount path
[pandora-kernel.git] / fs / jbd2 / journal.c
index c19b8ce..039b8ae 100644 (file)
@@ -1340,11 +1340,12 @@ out:
 /**
  * jbd2_mark_journal_empty() - Mark on disk journal as empty.
  * @journal: The journal to update.
+ * @write_op: With which operation should we write the journal sb
  *
  * Update a journal's dynamic superblock fields to show that journal is empty.
  * Write updated superblock to disk waiting for IO to complete.
  */
-static void jbd2_mark_journal_empty(journal_t *journal)
+static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
 {
        journal_superblock_t *sb = journal->j_superblock;
 
@@ -1357,7 +1358,7 @@ static void jbd2_mark_journal_empty(journal_t *journal)
        sb->s_start    = cpu_to_be32(0);
        read_unlock(&journal->j_state_lock);
 
-       jbd2_write_superblock(journal, WRITE_FUA);
+       jbd2_write_superblock(journal, write_op);
 
        /* Log is no longer empty */
        write_lock(&journal->j_state_lock);
@@ -1593,7 +1594,13 @@ int jbd2_journal_destroy(journal_t *journal)
        if (journal->j_sb_buffer) {
                if (!is_journal_aborted(journal)) {
                        mutex_lock(&journal->j_checkpoint_mutex);
-                       jbd2_mark_journal_empty(journal);
+
+                       write_lock(&journal->j_state_lock);
+                       journal->j_tail_sequence =
+                               ++journal->j_transaction_sequence;
+                       write_unlock(&journal->j_state_lock);
+
+                       jbd2_mark_journal_empty(journal, WRITE_FLUSH_FUA);
                        mutex_unlock(&journal->j_checkpoint_mutex);
                } else
                        err = -EIO;
@@ -1859,7 +1866,7 @@ int jbd2_journal_flush(journal_t *journal)
         * the magic code for a fully-recovered superblock.  Any future
         * commits of data to the journal will restore the current
         * s_start value. */
-       jbd2_mark_journal_empty(journal);
+       jbd2_mark_journal_empty(journal, WRITE_FUA);
        mutex_unlock(&journal->j_checkpoint_mutex);
        write_lock(&journal->j_state_lock);
        J_ASSERT(!journal->j_running_transaction);
@@ -1905,7 +1912,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
        if (write) {
                /* Lock to make assertions happy... */
                mutex_lock(&journal->j_checkpoint_mutex);
-               jbd2_mark_journal_empty(journal);
+               jbd2_mark_journal_empty(journal, WRITE_FUA);
                mutex_unlock(&journal->j_checkpoint_mutex);
        }