diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-11-06 17:50:21 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-11-06 17:50:21 -0500 |
commit | fb68407b0d9efba962c03f55009c797e22f024bc (patch) | |
tree | b3f33f513969d6f77c5b6a6f71b662057d3440a5 | |
parent | c3a326a657562dab81acf05aee106dc1fe345eb4 (diff) |
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>
-rw-r--r-- | fs/jbd2/checkpoint.c | 2 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 13 | ||||
-rw-r--r-- | include/linux/jbd2.h | 4 |
3 files changed, 11 insertions, 8 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index adc08ec875ed..17159cacbd9e 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -682,6 +682,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
682 | safely remove this transaction from the log */ | 682 | safely remove this transaction from the log */ |
683 | 683 | ||
684 | __jbd2_journal_drop_transaction(journal, transaction); | 684 | __jbd2_journal_drop_transaction(journal, transaction); |
685 | kfree(transaction); | ||
685 | 686 | ||
686 | /* Just in case anybody was waiting for more transactions to be | 687 | /* Just in case anybody was waiting for more transactions to be |
687 | checkpointed... */ | 688 | checkpointed... */ |
@@ -756,5 +757,4 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact | |||
756 | J_ASSERT(journal->j_running_transaction != transaction); | 757 | J_ASSERT(journal->j_running_transaction != transaction); |
757 | 758 | ||
758 | jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid); | 759 | jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid); |
759 | kfree(transaction); | ||
760 | } | 760 | } |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index f22d1828ea85..0ad84162c425 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -363,7 +363,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
363 | int space_left = 0; | 363 | int space_left = 0; |
364 | int first_tag = 0; | 364 | int first_tag = 0; |
365 | int tag_flag; | 365 | int tag_flag; |
366 | int i; | 366 | int i, to_free = 0; |
367 | int tag_bytes = journal_tag_bytes(journal); | 367 | int tag_bytes = journal_tag_bytes(journal); |
368 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | 368 | struct buffer_head *cbh = NULL; /* For transactional checksums */ |
369 | __u32 crc32_sum = ~0; | 369 | __u32 crc32_sum = ~0; |
@@ -1011,12 +1011,10 @@ restart_loop: | |||
1011 | journal->j_average_commit_time = commit_time; | 1011 | journal->j_average_commit_time = commit_time; |
1012 | spin_unlock(&journal->j_state_lock); | 1012 | spin_unlock(&journal->j_state_lock); |
1013 | 1013 | ||
1014 | if (journal->j_commit_callback) | ||
1015 | journal->j_commit_callback(journal, commit_transaction); | ||
1016 | |||
1017 | if (commit_transaction->t_checkpoint_list == NULL && | 1014 | if (commit_transaction->t_checkpoint_list == NULL && |
1018 | commit_transaction->t_checkpoint_io_list == NULL) { | 1015 | commit_transaction->t_checkpoint_io_list == NULL) { |
1019 | __jbd2_journal_drop_transaction(journal, commit_transaction); | 1016 | __jbd2_journal_drop_transaction(journal, commit_transaction); |
1017 | to_free = 1; | ||
1020 | } else { | 1018 | } else { |
1021 | if (journal->j_checkpoint_transactions == NULL) { | 1019 | if (journal->j_checkpoint_transactions == NULL) { |
1022 | journal->j_checkpoint_transactions = commit_transaction; | 1020 | journal->j_checkpoint_transactions = commit_transaction; |
@@ -1035,11 +1033,16 @@ restart_loop: | |||
1035 | } | 1033 | } |
1036 | spin_unlock(&journal->j_list_lock); | 1034 | spin_unlock(&journal->j_list_lock); |
1037 | 1035 | ||
1036 | if (journal->j_commit_callback) | ||
1037 | journal->j_commit_callback(journal, commit_transaction); | ||
1038 | |||
1038 | trace_mark(jbd2_end_commit, "dev %s transaction %d head %d", | 1039 | trace_mark(jbd2_end_commit, "dev %s transaction %d head %d", |
1039 | journal->j_devname, journal->j_commit_sequence, | 1040 | journal->j_devname, commit_transaction->t_tid, |
1040 | journal->j_tail_sequence); | 1041 | journal->j_tail_sequence); |
1041 | jbd_debug(1, "JBD: commit %d complete, head %d\n", | 1042 | jbd_debug(1, "JBD: commit %d complete, head %d\n", |
1042 | journal->j_commit_sequence, journal->j_tail_sequence); | 1043 | journal->j_commit_sequence, journal->j_tail_sequence); |
1044 | if (to_free) | ||
1045 | kfree(commit_transaction); | ||
1043 | 1046 | ||
1044 | wake_up(&journal->j_wait_done_commit); | 1047 | wake_up(&journal->j_wait_done_commit); |
1045 | } | 1048 | } |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 004c9a8d63ed..9d82084a1605 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -1179,8 +1179,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid); | |||
1179 | int jbd2_log_do_checkpoint(journal_t *journal); | 1179 | int jbd2_log_do_checkpoint(journal_t *journal); |
1180 | 1180 | ||
1181 | void __jbd2_log_wait_for_space(journal_t *journal); | 1181 | void __jbd2_log_wait_for_space(journal_t *journal); |
1182 | extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *); | 1182 | extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *); |
1183 | extern int jbd2_cleanup_journal_tail(journal_t *); | 1183 | extern int jbd2_cleanup_journal_tail(journal_t *); |
1184 | 1184 | ||
1185 | /* Debugging code only: */ | 1185 | /* Debugging code only: */ |
1186 | 1186 | ||