sysv: replace inode uid,gid,mode initialization with helper function
[safe/jmp/linux-2.6] / fs / jbd2 / checkpoint.c
index adc08ec..30beb11 100644 (file)
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/marker.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <trace/events/jbd2.h>
 
 /*
  * Unlink a buffer from a transaction checkpoint list.
@@ -358,8 +359,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
         * journal straight away.
         */
        result = jbd2_cleanup_journal_tail(journal);
-       trace_mark(jbd2_checkpoint, "dev %s need_checkpoint %d",
-                  journal->j_devname, result);
+       trace_jbd2_checkpoint(journal, result);
        jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
        if (result <= 0)
                return result;
@@ -507,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",
@@ -516,6 +517,20 @@ 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, NULL);
        if (!(journal->j_flags & JBD2_ABORT))
                jbd2_journal_update_superblock(journal, 1);
        return 0;
@@ -644,6 +659,7 @@ out:
 
 int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
 {
+       struct transaction_chp_stats_s *stats;
        transaction_t *transaction;
        journal_t *journal;
        int ret = 0;
@@ -680,8 +696,15 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
 
        /* OK, that was the last buffer for the transaction: we can now
           safely remove this transaction from the log */
+       stats = &transaction->t_chp_stats;
+       if (stats->cs_chp_time)
+               stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
+                                                   jiffies);
+       trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
+                                   transaction->t_tid, stats);
 
        __jbd2_journal_drop_transaction(journal, transaction);
+       kfree(transaction);
 
        /* Just in case anybody was waiting for more transactions to be
            checkpointed... */
@@ -756,5 +779,4 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
        J_ASSERT(journal->j_running_transaction != transaction);
 
        jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
-       kfree(transaction);
 }