diff options
Diffstat (limited to 'fs/jbd2/commit.c')
-rw-r--r-- | fs/jbd2/commit.c | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 750c70148eff..0f53946f13c1 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -382,7 +382,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
382 | int space_left = 0; | 382 | int space_left = 0; |
383 | int first_tag = 0; | 383 | int first_tag = 0; |
384 | int tag_flag; | 384 | int tag_flag; |
385 | int i, to_free = 0; | 385 | int i; |
386 | int tag_bytes = journal_tag_bytes(journal); | 386 | int tag_bytes = journal_tag_bytes(journal); |
387 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | 387 | struct buffer_head *cbh = NULL; /* For transactional checksums */ |
388 | __u32 crc32_sum = ~0; | 388 | __u32 crc32_sum = ~0; |
@@ -1134,7 +1134,7 @@ restart_loop: | |||
1134 | journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; | 1134 | journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; |
1135 | spin_unlock(&journal->j_history_lock); | 1135 | spin_unlock(&journal->j_history_lock); |
1136 | 1136 | ||
1137 | commit_transaction->t_state = T_FINISHED; | 1137 | commit_transaction->t_state = T_COMMIT_CALLBACK; |
1138 | J_ASSERT(commit_transaction == journal->j_committing_transaction); | 1138 | J_ASSERT(commit_transaction == journal->j_committing_transaction); |
1139 | journal->j_commit_sequence = commit_transaction->t_tid; | 1139 | journal->j_commit_sequence = commit_transaction->t_tid; |
1140 | journal->j_committing_transaction = NULL; | 1140 | journal->j_committing_transaction = NULL; |
@@ -1149,38 +1149,44 @@ restart_loop: | |||
1149 | journal->j_average_commit_time*3) / 4; | 1149 | journal->j_average_commit_time*3) / 4; |
1150 | else | 1150 | else |
1151 | journal->j_average_commit_time = commit_time; | 1151 | journal->j_average_commit_time = commit_time; |
1152 | |||
1152 | write_unlock(&journal->j_state_lock); | 1153 | write_unlock(&journal->j_state_lock); |
1153 | 1154 | ||
1154 | if (commit_transaction->t_checkpoint_list == NULL && | 1155 | if (journal->j_checkpoint_transactions == NULL) { |
1155 | commit_transaction->t_checkpoint_io_list == NULL) { | 1156 | journal->j_checkpoint_transactions = commit_transaction; |
1156 | __jbd2_journal_drop_transaction(journal, commit_transaction); | 1157 | commit_transaction->t_cpnext = commit_transaction; |
1157 | to_free = 1; | 1158 | commit_transaction->t_cpprev = commit_transaction; |
1158 | } else { | 1159 | } else { |
1159 | if (journal->j_checkpoint_transactions == NULL) { | 1160 | commit_transaction->t_cpnext = |
1160 | journal->j_checkpoint_transactions = commit_transaction; | 1161 | journal->j_checkpoint_transactions; |
1161 | commit_transaction->t_cpnext = commit_transaction; | 1162 | commit_transaction->t_cpprev = |
1162 | commit_transaction->t_cpprev = commit_transaction; | 1163 | commit_transaction->t_cpnext->t_cpprev; |
1163 | } else { | 1164 | commit_transaction->t_cpnext->t_cpprev = |
1164 | commit_transaction->t_cpnext = | 1165 | commit_transaction; |
1165 | journal->j_checkpoint_transactions; | 1166 | commit_transaction->t_cpprev->t_cpnext = |
1166 | commit_transaction->t_cpprev = | ||
1167 | commit_transaction->t_cpnext->t_cpprev; | ||
1168 | commit_transaction->t_cpnext->t_cpprev = | ||
1169 | commit_transaction; | ||
1170 | commit_transaction->t_cpprev->t_cpnext = | ||
1171 | commit_transaction; | 1167 | commit_transaction; |
1172 | } | ||
1173 | } | 1168 | } |
1174 | spin_unlock(&journal->j_list_lock); | 1169 | spin_unlock(&journal->j_list_lock); |
1175 | 1170 | /* Drop all spin_locks because commit_callback may be block. | |
1171 | * __journal_remove_checkpoint() can not destroy transaction | ||
1172 | * under us because it is not marked as T_FINISHED yet */ | ||
1176 | if (journal->j_commit_callback) | 1173 | if (journal->j_commit_callback) |
1177 | journal->j_commit_callback(journal, commit_transaction); | 1174 | journal->j_commit_callback(journal, commit_transaction); |
1178 | 1175 | ||
1179 | trace_jbd2_end_commit(journal, commit_transaction); | 1176 | trace_jbd2_end_commit(journal, commit_transaction); |
1180 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", | 1177 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", |
1181 | journal->j_commit_sequence, journal->j_tail_sequence); | 1178 | journal->j_commit_sequence, journal->j_tail_sequence); |
1182 | if (to_free) | ||
1183 | jbd2_journal_free_transaction(commit_transaction); | ||
1184 | 1179 | ||
1180 | write_lock(&journal->j_state_lock); | ||
1181 | spin_lock(&journal->j_list_lock); | ||
1182 | commit_transaction->t_state = T_FINISHED; | ||
1183 | /* Recheck checkpoint lists after j_list_lock was dropped */ | ||
1184 | if (commit_transaction->t_checkpoint_list == NULL && | ||
1185 | commit_transaction->t_checkpoint_io_list == NULL) { | ||
1186 | __jbd2_journal_drop_transaction(journal, commit_transaction); | ||
1187 | jbd2_journal_free_transaction(commit_transaction); | ||
1188 | } | ||
1189 | spin_unlock(&journal->j_list_lock); | ||
1190 | write_unlock(&journal->j_state_lock); | ||
1185 | wake_up(&journal->j_wait_done_commit); | 1191 | wake_up(&journal->j_wait_done_commit); |
1186 | } | 1192 | } |