jbd2: Call journal commit callback without holding j_list_lock
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>
This commit is contained in:
committed by
Theodore Ts'o
parent
c3a326a657
commit
fb68407b0d
@@ -682,6 +682,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
|
|||||||
safely remove this transaction from the log */
|
safely remove this transaction from the log */
|
||||||
|
|
||||||
__jbd2_journal_drop_transaction(journal, transaction);
|
__jbd2_journal_drop_transaction(journal, transaction);
|
||||||
|
kfree(transaction);
|
||||||
|
|
||||||
/* Just in case anybody was waiting for more transactions to be
|
/* Just in case anybody was waiting for more transactions to be
|
||||||
checkpointed... */
|
checkpointed... */
|
||||||
@@ -756,5 +757,4 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
|
|||||||
J_ASSERT(journal->j_running_transaction != transaction);
|
J_ASSERT(journal->j_running_transaction != transaction);
|
||||||
|
|
||||||
jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
|
jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
|
||||||
kfree(transaction);
|
|
||||||
}
|
}
|
||||||
|
@@ -363,7 +363,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
|||||||
int space_left = 0;
|
int space_left = 0;
|
||||||
int first_tag = 0;
|
int first_tag = 0;
|
||||||
int tag_flag;
|
int tag_flag;
|
||||||
int i;
|
int i, to_free = 0;
|
||||||
int tag_bytes = journal_tag_bytes(journal);
|
int tag_bytes = journal_tag_bytes(journal);
|
||||||
struct buffer_head *cbh = NULL; /* For transactional checksums */
|
struct buffer_head *cbh = NULL; /* For transactional checksums */
|
||||||
__u32 crc32_sum = ~0;
|
__u32 crc32_sum = ~0;
|
||||||
@@ -1011,12 +1011,10 @@ restart_loop:
|
|||||||
journal->j_average_commit_time = commit_time;
|
journal->j_average_commit_time = commit_time;
|
||||||
spin_unlock(&journal->j_state_lock);
|
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 &&
|
if (commit_transaction->t_checkpoint_list == NULL &&
|
||||||
commit_transaction->t_checkpoint_io_list == NULL) {
|
commit_transaction->t_checkpoint_io_list == NULL) {
|
||||||
__jbd2_journal_drop_transaction(journal, commit_transaction);
|
__jbd2_journal_drop_transaction(journal, commit_transaction);
|
||||||
|
to_free = 1;
|
||||||
} else {
|
} else {
|
||||||
if (journal->j_checkpoint_transactions == NULL) {
|
if (journal->j_checkpoint_transactions == NULL) {
|
||||||
journal->j_checkpoint_transactions = commit_transaction;
|
journal->j_checkpoint_transactions = commit_transaction;
|
||||||
@@ -1035,11 +1033,16 @@ restart_loop:
|
|||||||
}
|
}
|
||||||
spin_unlock(&journal->j_list_lock);
|
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",
|
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);
|
journal->j_tail_sequence);
|
||||||
jbd_debug(1, "JBD: commit %d complete, head %d\n",
|
jbd_debug(1, "JBD: commit %d complete, head %d\n",
|
||||||
journal->j_commit_sequence, journal->j_tail_sequence);
|
journal->j_commit_sequence, journal->j_tail_sequence);
|
||||||
|
if (to_free)
|
||||||
|
kfree(commit_transaction);
|
||||||
|
|
||||||
wake_up(&journal->j_wait_done_commit);
|
wake_up(&journal->j_wait_done_commit);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user