|
@@ -382,7 +382,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
|
|
|
int space_left = 0;
|
|
|
int first_tag = 0;
|
|
|
int tag_flag;
|
|
|
- int i, to_free = 0;
|
|
|
+ int i;
|
|
|
int tag_bytes = journal_tag_bytes(journal);
|
|
|
struct buffer_head *cbh = NULL; /* For transactional checksums */
|
|
|
__u32 crc32_sum = ~0;
|
|
@@ -1134,7 +1134,7 @@ restart_loop:
|
|
|
journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
|
|
|
spin_unlock(&journal->j_history_lock);
|
|
|
|
|
|
- commit_transaction->t_state = T_FINISHED;
|
|
|
+ commit_transaction->t_state = T_COMMIT_CALLBACK;
|
|
|
J_ASSERT(commit_transaction == journal->j_committing_transaction);
|
|
|
journal->j_commit_sequence = commit_transaction->t_tid;
|
|
|
journal->j_committing_transaction = NULL;
|
|
@@ -1149,38 +1149,44 @@ restart_loop:
|
|
|
journal->j_average_commit_time*3) / 4;
|
|
|
else
|
|
|
journal->j_average_commit_time = commit_time;
|
|
|
+
|
|
|
write_unlock(&journal->j_state_lock);
|
|
|
|
|
|
- if (commit_transaction->t_checkpoint_list == NULL &&
|
|
|
- commit_transaction->t_checkpoint_io_list == NULL) {
|
|
|
- __jbd2_journal_drop_transaction(journal, commit_transaction);
|
|
|
- to_free = 1;
|
|
|
+ if (journal->j_checkpoint_transactions == NULL) {
|
|
|
+ journal->j_checkpoint_transactions = commit_transaction;
|
|
|
+ commit_transaction->t_cpnext = commit_transaction;
|
|
|
+ commit_transaction->t_cpprev = commit_transaction;
|
|
|
} else {
|
|
|
- if (journal->j_checkpoint_transactions == NULL) {
|
|
|
- journal->j_checkpoint_transactions = commit_transaction;
|
|
|
- commit_transaction->t_cpnext = commit_transaction;
|
|
|
- commit_transaction->t_cpprev = commit_transaction;
|
|
|
- } else {
|
|
|
- commit_transaction->t_cpnext =
|
|
|
- journal->j_checkpoint_transactions;
|
|
|
- commit_transaction->t_cpprev =
|
|
|
- commit_transaction->t_cpnext->t_cpprev;
|
|
|
- commit_transaction->t_cpnext->t_cpprev =
|
|
|
- commit_transaction;
|
|
|
- commit_transaction->t_cpprev->t_cpnext =
|
|
|
+ commit_transaction->t_cpnext =
|
|
|
+ journal->j_checkpoint_transactions;
|
|
|
+ commit_transaction->t_cpprev =
|
|
|
+ commit_transaction->t_cpnext->t_cpprev;
|
|
|
+ commit_transaction->t_cpnext->t_cpprev =
|
|
|
+ commit_transaction;
|
|
|
+ commit_transaction->t_cpprev->t_cpnext =
|
|
|
commit_transaction;
|
|
|
- }
|
|
|
}
|
|
|
spin_unlock(&journal->j_list_lock);
|
|
|
-
|
|
|
+ /* Drop all spin_locks because commit_callback may be block.
|
|
|
+ * __journal_remove_checkpoint() can not destroy transaction
|
|
|
+ * under us because it is not marked as T_FINISHED yet */
|
|
|
if (journal->j_commit_callback)
|
|
|
journal->j_commit_callback(journal, commit_transaction);
|
|
|
|
|
|
trace_jbd2_end_commit(journal, commit_transaction);
|
|
|
jbd_debug(1, "JBD2: commit %d complete, head %d\n",
|
|
|
journal->j_commit_sequence, journal->j_tail_sequence);
|
|
|
- if (to_free)
|
|
|
- jbd2_journal_free_transaction(commit_transaction);
|
|
|
|
|
|
+ write_lock(&journal->j_state_lock);
|
|
|
+ spin_lock(&journal->j_list_lock);
|
|
|
+ commit_transaction->t_state = T_FINISHED;
|
|
|
+ /* Recheck checkpoint lists after j_list_lock was dropped */
|
|
|
+ if (commit_transaction->t_checkpoint_list == NULL &&
|
|
|
+ commit_transaction->t_checkpoint_io_list == NULL) {
|
|
|
+ __jbd2_journal_drop_transaction(journal, commit_transaction);
|
|
|
+ jbd2_journal_free_transaction(commit_transaction);
|
|
|
+ }
|
|
|
+ spin_unlock(&journal->j_list_lock);
|
|
|
+ write_unlock(&journal->j_state_lock);
|
|
|
wake_up(&journal->j_wait_done_commit);
|
|
|
}
|