Merge remote-tracking branch 'asoc/fix/ux500' into asoc-linus
[firefly-linux-kernel-4.4.55.git] / fs / jbd2 / checkpoint.c
index d49d202903fb13cb9e8b663c1c6aea181f38d37a..c78841ee81cf31a0c4c67a23bca294a32720cb5f 100644 (file)
@@ -88,14 +88,13 @@ static inline void __buffer_relink_io(struct journal_head *jh)
  * whole transaction.
  *
  * Requires j_list_lock
- * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
  */
 static int __try_to_free_cp_buf(struct journal_head *jh)
 {
        int ret = 0;
        struct buffer_head *bh = jh2bh(jh);
 
-       if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
+       if (jh->b_transaction == NULL && !buffer_locked(bh) &&
            !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
                /*
                 * Get our reference so that bh cannot be freed before
@@ -104,11 +103,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
                get_bh(bh);
                JBUFFER_TRACE(jh, "remove from checkpoint list");
                ret = __jbd2_journal_remove_checkpoint(jh) + 1;
-               jbd_unlock_bh_state(bh);
                BUFFER_TRACE(bh, "release");
                __brelse(bh);
-       } else {
-               jbd_unlock_bh_state(bh);
        }
        return ret;
 }
@@ -179,21 +175,6 @@ void __jbd2_log_wait_for_space(journal_t *journal)
        }
 }
 
-/*
- * We were unable to perform jbd_trylock_bh_state() inside j_list_lock.
- * The caller must restart a list walk.  Wait for someone else to run
- * jbd_unlock_bh_state().
- */
-static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
-       __releases(journal->j_list_lock)
-{
-       get_bh(bh);
-       spin_unlock(&journal->j_list_lock);
-       jbd_lock_bh_state(bh);
-       jbd_unlock_bh_state(bh);
-       put_bh(bh);
-}
-
 /*
  * Clean up transaction's list of buffers submitted for io.
  * We wait for any pending IO to complete and remove any clean
@@ -222,15 +203,9 @@ restart:
        while (!released && transaction->t_checkpoint_io_list) {
                jh = transaction->t_checkpoint_io_list;
                bh = jh2bh(jh);
-               if (!jbd_trylock_bh_state(bh)) {
-                       jbd_sync_bh(journal, bh);
-                       spin_lock(&journal->j_list_lock);
-                       goto restart;
-               }
                get_bh(bh);
                if (buffer_locked(bh)) {
                        spin_unlock(&journal->j_list_lock);
-                       jbd_unlock_bh_state(bh);
                        wait_on_buffer(bh);
                        /* the journal_head may have gone by now */
                        BUFFER_TRACE(bh, "brelse");
@@ -246,7 +221,6 @@ restart:
                 * it has been written out and so we can drop it from the list
                 */
                released = __jbd2_journal_remove_checkpoint(jh);
-               jbd_unlock_bh_state(bh);
                __brelse(bh);
        }
 
@@ -266,7 +240,6 @@ __flush_batch(journal_t *journal, int *batch_count)
 
        for (i = 0; i < *batch_count; i++) {
                struct buffer_head *bh = journal->j_chkpt_bhs[i];
-               clear_buffer_jwrite(bh);
                BUFFER_TRACE(bh, "brelse");
                __brelse(bh);
        }
@@ -281,7 +254,6 @@ __flush_batch(journal_t *journal, int *batch_count)
  * be written out.
  *
  * Called with j_list_lock held and drops it if 1 is returned
- * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
  */
 static int __process_buffer(journal_t *journal, struct journal_head *jh,
                            int *batch_count, transaction_t *transaction)
@@ -292,7 +264,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
        if (buffer_locked(bh)) {
                get_bh(bh);
                spin_unlock(&journal->j_list_lock);
-               jbd_unlock_bh_state(bh);
                wait_on_buffer(bh);
                /* the journal_head may have gone by now */
                BUFFER_TRACE(bh, "brelse");
@@ -304,7 +275,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
 
                transaction->t_chp_stats.cs_forced_to_close++;
                spin_unlock(&journal->j_list_lock);
-               jbd_unlock_bh_state(bh);
                if (unlikely(journal->j_flags & JBD2_UNMOUNT))
                        /*
                         * The journal thread is dead; so starting and
@@ -323,11 +293,9 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
                if (unlikely(buffer_write_io_error(bh)))
                        ret = -EIO;
                get_bh(bh);
-               J_ASSERT_JH(jh, !buffer_jbddirty(bh));
                BUFFER_TRACE(bh, "remove from checkpoint");
                __jbd2_journal_remove_checkpoint(jh);
                spin_unlock(&journal->j_list_lock);
-               jbd_unlock_bh_state(bh);
                __brelse(bh);
        } else {
                /*
@@ -340,10 +308,8 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
                BUFFER_TRACE(bh, "queue");
                get_bh(bh);
                J_ASSERT_BH(bh, !buffer_jwrite(bh));
-               set_buffer_jwrite(bh);
                journal->j_chkpt_bhs[*batch_count] = bh;
                __buffer_relink_io(jh);
-               jbd_unlock_bh_state(bh);
                transaction->t_chp_stats.cs_written++;
                (*batch_count)++;
                if (*batch_count == JBD2_NR_BATCH) {
@@ -407,15 +373,7 @@ restart:
                int retry = 0, err;
 
                while (!retry && transaction->t_checkpoint_list) {
-                       struct buffer_head *bh;
-
                        jh = transaction->t_checkpoint_list;
-                       bh = jh2bh(jh);
-                       if (!jbd_trylock_bh_state(bh)) {
-                               jbd_sync_bh(journal, bh);
-                               retry = 1;
-                               break;
-                       }
                        retry = __process_buffer(journal, jh, &batch_count,
                                                 transaction);
                        if (retry < 0 && !result)
@@ -478,79 +436,28 @@ out:
 
 int jbd2_cleanup_journal_tail(journal_t *journal)
 {
-       transaction_t * transaction;
        tid_t           first_tid;
-       unsigned long   blocknr, freed;
+       unsigned long   blocknr;
 
        if (is_journal_aborted(journal))
                return 1;
 
-       /* OK, work out the oldest transaction remaining in the log, and
-        * the log block it starts at.
-        *
-        * If the log is now empty, we need to work out which is the
-        * next transaction ID we will write, and where it will
-        * start. */
-
-       write_lock(&journal->j_state_lock);
-       spin_lock(&journal->j_list_lock);
-       transaction = journal->j_checkpoint_transactions;
-       if (transaction) {
-               first_tid = transaction->t_tid;
-               blocknr = transaction->t_log_start;
-       } else if ((transaction = journal->j_committing_transaction) != NULL) {
-               first_tid = transaction->t_tid;
-               blocknr = transaction->t_log_start;
-       } else if ((transaction = journal->j_running_transaction) != NULL) {
-               first_tid = transaction->t_tid;
-               blocknr = journal->j_head;
-       } else {
-               first_tid = journal->j_transaction_sequence;
-               blocknr = journal->j_head;
-       }
-       spin_unlock(&journal->j_list_lock);
-       J_ASSERT(blocknr != 0);
-
-       /* If the oldest pinned transaction is at the tail of the log
-           already then there's not much we can do right now. */
-       if (journal->j_tail_sequence == first_tid) {
-               write_unlock(&journal->j_state_lock);
+       if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr))
                return 1;
-       }
-
-       /* OK, update the superblock to recover the freed space.
-        * Physical blocks come first: have we wrapped beyond the end of
-        * the log?  */
-       freed = blocknr - journal->j_tail;
-       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",
-                 journal->j_tail_sequence, first_tid, blocknr, freed);
-
-       journal->j_free += freed;
-       journal->j_tail_sequence = first_tid;
-       journal->j_tail = blocknr;
-       write_unlock(&journal->j_state_lock);
+       J_ASSERT(blocknr != 0);
 
        /*
-        * 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.
+        * We need to make sure that any blocks that were recently written out
+        * --- perhaps by jbd2_log_do_checkpoint() --- are flushed out before
+        * we drop the transactions from the journal. It's unlikely this will
+        * be necessary, especially with an 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))
+       if (journal->j_flags & JBD2_BARRIER)
                blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
-       if (!(journal->j_flags & JBD2_ABORT))
-               jbd2_journal_update_superblock(journal, 1);
+
+       __jbd2_update_log_tail(journal, first_tid, blocknr);
        return 0;
 }
 
@@ -582,15 +489,12 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
        do {
                jh = next_jh;
                next_jh = jh->b_cpnext;
-               /* Use trylock because of the ranking */
-               if (jbd_trylock_bh_state(jh2bh(jh))) {
-                       ret = __try_to_free_cp_buf(jh);
-                       if (ret) {
-                               freed++;
-                               if (ret == 2) {
-                                       *released = 1;
-                                       return freed;
-                               }
+               ret = __try_to_free_cp_buf(jh);
+               if (ret) {
+                       freed++;
+                       if (ret == 2) {
+                               *released = 1;
+                               return freed;
                        }
                }
                /*
@@ -673,9 +577,7 @@ out:
  * The function can free jh and bh.
  *
  * This function is called with j_list_lock held.
- * This function is called with jbd_lock_bh_state(jh2bh(jh))
  */
-
 int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
 {
        struct transaction_chp_stats_s *stats;
@@ -722,7 +624,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
                                    transaction->t_tid, stats);
 
        __jbd2_journal_drop_transaction(journal, transaction);
-       kfree(transaction);
+       jbd2_journal_free_transaction(transaction);
 
        /* Just in case anybody was waiting for more transactions to be
            checkpointed... */
@@ -797,5 +699,7 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
        J_ASSERT(journal->j_committing_transaction != transaction);
        J_ASSERT(journal->j_running_transaction != transaction);
 
+       trace_jbd2_drop_transaction(journal, transaction);
+
        jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
 }