jbd2: Call journal commit callback without holding j_list_lock
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Thu, 6 Nov 2008 22:50:21 +0000 (17:50 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 6 Nov 2008 22:50:21 +0000 (17:50 -0500)
Avoid freeing the transaction in __jbd2_journal_drop_transaction() so
the journal commit callback can run without holding j_list_lock, to
avoid lock contention on this spinlock.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
include/linux/jbd2.h

index adc08ec875edb427962e8a24d92eddd82930cd27..17159cacbd9ec95aba6f7b0a942680322858159d 100644 (file)
@@ -682,6 +682,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
           safely remove this transaction from the log */
 
        __jbd2_journal_drop_transaction(journal, transaction);
+       kfree(transaction);
 
        /* Just in case anybody was waiting for more transactions to be
            checkpointed... */
@@ -756,5 +757,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);
 }
index f22d1828ea8572d22c916322b3bd30a25d25227f..0ad84162c425cf3b7fd9f329a24cc81aa1c7959c 100644 (file)
@@ -363,7 +363,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        int space_left = 0;
        int first_tag = 0;
        int tag_flag;
-       int i;
+       int i, to_free = 0;
        int tag_bytes = journal_tag_bytes(journal);
        struct buffer_head *cbh = NULL; /* For transactional checksums */
        __u32 crc32_sum = ~0;
@@ -1011,12 +1011,10 @@ restart_loop:
                journal->j_average_commit_time = commit_time;
        spin_unlock(&journal->j_state_lock);
 
-       if (journal->j_commit_callback)
-               journal->j_commit_callback(journal, commit_transaction);
-
        if (commit_transaction->t_checkpoint_list == NULL &&
            commit_transaction->t_checkpoint_io_list == NULL) {
                __jbd2_journal_drop_transaction(journal, commit_transaction);
+               to_free = 1;
        } else {
                if (journal->j_checkpoint_transactions == NULL) {
                        journal->j_checkpoint_transactions = commit_transaction;
@@ -1035,11 +1033,16 @@ restart_loop:
        }
        spin_unlock(&journal->j_list_lock);
 
+       if (journal->j_commit_callback)
+               journal->j_commit_callback(journal, commit_transaction);
+
        trace_mark(jbd2_end_commit, "dev %s transaction %d head %d",
-                  journal->j_devname, journal->j_commit_sequence,
+                  journal->j_devname, commit_transaction->t_tid,
                   journal->j_tail_sequence);
        jbd_debug(1, "JBD: commit %d complete, head %d\n",
                  journal->j_commit_sequence, journal->j_tail_sequence);
+       if (to_free)
+               kfree(commit_transaction);
 
        wake_up(&journal->j_wait_done_commit);
 }
index 004c9a8d63ed06fe63526bfbc85e2d72c9fc2ca6..9d82084a160544bec59c9b3d0ad7fbb003e6ccdf 100644 (file)
@@ -1179,8 +1179,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid);
 int jbd2_log_do_checkpoint(journal_t *journal);
 
 void __jbd2_log_wait_for_space(journal_t *journal);
-extern void    __jbd2_journal_drop_transaction(journal_t *, transaction_t *);
-extern int     jbd2_cleanup_journal_tail(journal_t *);
+extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *);
+extern int jbd2_cleanup_journal_tail(journal_t *);
 
 /* Debugging code only: */