@@ -382,7 +382,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
382
382
int space_left = 0 ;
383
383
int first_tag = 0 ;
384
384
int tag_flag ;
385
- int i , to_free = 0 ;
385
+ int i ;
386
386
int tag_bytes = journal_tag_bytes (journal );
387
387
struct buffer_head * cbh = NULL ; /* For transactional checksums */
388
388
__u32 crc32_sum = ~0 ;
@@ -1134,7 +1134,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
1134
1134
journal -> j_stats .run .rs_blocks_logged += stats .run .rs_blocks_logged ;
1135
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
1138
J_ASSERT (commit_transaction == journal -> j_committing_transaction );
1139
1139
journal -> j_commit_sequence = commit_transaction -> t_tid ;
1140
1140
journal -> j_committing_transaction = NULL ;
@@ -1149,38 +1149,44 @@ void jbd2_journal_commit_transaction(journal_t *journal)
1149
1149
journal -> j_average_commit_time * 3 ) / 4 ;
1150
1150
else
1151
1151
journal -> j_average_commit_time = commit_time ;
1152
+
1152
1153
write_unlock (& journal -> j_state_lock );
1153
1154
1154
- if (commit_transaction -> t_checkpoint_list == NULL &&
1155
- commit_transaction -> t_checkpoint_io_list == NULL ) {
1156
- __jbd2_journal_drop_transaction ( journal , commit_transaction ) ;
1157
- to_free = 1 ;
1155
+ if (journal -> j_checkpoint_transactions == NULL ) {
1156
+ journal -> j_checkpoint_transactions = commit_transaction ;
1157
+ commit_transaction -> t_cpnext = commit_transaction ;
1158
+ commit_transaction -> t_cpprev = commit_transaction ;
1158
1159
} else {
1159
- if (journal -> j_checkpoint_transactions == NULL ) {
1160
- journal -> j_checkpoint_transactions = commit_transaction ;
1161
- commit_transaction -> t_cpnext = commit_transaction ;
1162
- commit_transaction -> t_cpprev = commit_transaction ;
1163
- } else {
1164
- commit_transaction -> t_cpnext =
1165
- journal -> j_checkpoint_transactions ;
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 =
1160
+ commit_transaction -> t_cpnext =
1161
+ journal -> j_checkpoint_transactions ;
1162
+ commit_transaction -> t_cpprev =
1163
+ commit_transaction -> t_cpnext -> t_cpprev ;
1164
+ commit_transaction -> t_cpnext -> t_cpprev =
1165
+ commit_transaction ;
1166
+ commit_transaction -> t_cpprev -> t_cpnext =
1171
1167
commit_transaction ;
1172
- }
1173
1168
}
1174
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
1173
if (journal -> j_commit_callback )
1177
1174
journal -> j_commit_callback (journal , commit_transaction );
1178
1175
1179
1176
trace_jbd2_end_commit (journal , commit_transaction );
1180
1177
jbd_debug (1 , "JBD2: commit %d complete, head %d\n" ,
1181
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
1191
wake_up (& journal -> j_wait_done_commit );
1186
1192
}
0 commit comments