diff options
-rw-r--r-- | fs/jbd2/checkpoint.c | 12 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 8 | ||||
-rw-r--r-- | include/linux/jbd2.h | 2 |
3 files changed, 12 insertions, 10 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 3fccde7ba008..7e958c86242f 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -602,15 +602,15 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
602 | 602 | ||
603 | /* | 603 | /* |
604 | * There is one special case to worry about: if we have just pulled the | 604 | * There is one special case to worry about: if we have just pulled the |
605 | * buffer off a committing transaction's forget list, then even if the | 605 | * buffer off a running or committing transaction's checkpoing list, |
606 | * checkpoint list is empty, the transaction obviously cannot be | 606 | * then even if the checkpoint list is empty, the transaction obviously |
607 | * dropped! | 607 | * cannot be dropped! |
608 | * | 608 | * |
609 | * The locking here around j_committing_transaction is a bit sleazy. | 609 | * The locking here around t_state is a bit sleazy. |
610 | * See the comment at the end of jbd2_journal_commit_transaction(). | 610 | * See the comment at the end of jbd2_journal_commit_transaction(). |
611 | */ | 611 | */ |
612 | if (transaction == journal->j_committing_transaction) { | 612 | if (transaction->t_state != T_FINISHED) { |
613 | JBUFFER_TRACE(jh, "belongs to committing transaction"); | 613 | JBUFFER_TRACE(jh, "belongs to running/committing transaction"); |
614 | goto out; | 614 | goto out; |
615 | } | 615 | } |
616 | 616 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 6986f334c643..39b5cee3dd8a 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -867,10 +867,10 @@ restart_loop: | |||
867 | } | 867 | } |
868 | spin_unlock(&journal->j_list_lock); | 868 | spin_unlock(&journal->j_list_lock); |
869 | /* | 869 | /* |
870 | * This is a bit sleazy. We borrow j_list_lock to protect | 870 | * This is a bit sleazy. We use j_list_lock to protect transition |
871 | * journal->j_committing_transaction in __jbd2_journal_remove_checkpoint. | 871 | * of a transaction into T_FINISHED state and calling |
872 | * Really, __jbd2_journal_remove_checkpoint should be using j_state_lock but | 872 | * __jbd2_journal_drop_transaction(). Otherwise we could race with |
873 | * it's a bit hassle to hold that across __jbd2_journal_remove_checkpoint | 873 | * other checkpointing code processing the transaction... |
874 | */ | 874 | */ |
875 | spin_lock(&journal->j_state_lock); | 875 | spin_lock(&journal->j_state_lock); |
876 | spin_lock(&journal->j_list_lock); | 876 | spin_lock(&journal->j_list_lock); |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index d5f7cff4cb28..d861ffd49821 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -442,6 +442,8 @@ struct transaction_s | |||
442 | /* | 442 | /* |
443 | * Transaction's current state | 443 | * Transaction's current state |
444 | * [no locking - only kjournald2 alters this] | 444 | * [no locking - only kjournald2 alters this] |
445 | * [j_list_lock] guards transition of a transaction into T_FINISHED | ||
446 | * state and subsequent call of __jbd2_journal_drop_transaction() | ||
445 | * FIXME: needs barriers | 447 | * FIXME: needs barriers |
446 | * KLUDGE: [use j_state_lock] | 448 | * KLUDGE: [use j_state_lock] |
447 | */ | 449 | */ |