Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[safe/jmp/linux-2.6] / fs / jbd2 / checkpoint.c
index ca0f5eb..076d1cc 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/jbd2.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
 #include <trace/events/jbd2.h>
 
 /*
@@ -506,6 +507,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
        if (blocknr < journal->j_tail)
                freed = freed + journal->j_last - journal->j_first;
 
+       trace_jbd2_cleanup_journal_tail(journal, first_tid, blocknr, freed);
        jbd_debug(1,
                  "Cleaning journal tail from %d to %d (offset %lu), "
                  "freeing %lu\n",
@@ -515,6 +517,21 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
        journal->j_tail_sequence = first_tid;
        journal->j_tail = blocknr;
        spin_unlock(&journal->j_state_lock);
+
+       /*
+        * If there is an external journal, we need to make sure that
+        * any data blocks that were recently written out --- perhaps
+        * by jbd2_log_do_checkpoint() --- are flushed out before we
+        * drop the transactions from the external journal.  It's
+        * unlikely this will be necessary, especially with a
+        * appropriately sized journal, but we need this to guarantee
+        * correctness.  Fortunately jbd2_cleanup_journal_tail()
+        * doesn't get called all that often.
+        */
+       if ((journal->j_fs_dev != journal->j_dev) &&
+           (journal->j_flags & JBD2_BARRIER))
+               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL,
+                       BLKDEV_IFL_WAIT);
        if (!(journal->j_flags & JBD2_ABORT))
                jbd2_journal_update_superblock(journal, 1);
        return 0;