Commit:     f5a7a6b0d9b6af7d46124ed3f6b3995225cb62d0
Parent:     36df53f4a3e445175fc1e9d7f433599482ec6d7f
Author:     Jan Kara <[EMAIL PROTECTED]>
AuthorDate: Mon Jan 28 23:58:27 2008 -0500
Committer:  Theodore Ts'o <[EMAIL PROTECTED]>
CommitDate: Mon Jan 28 23:58:27 2008 -0500

    jbd2: Fix assertion failure in fs/jbd2/checkpoint.c
    Before we start committing a transaction, we call
    __journal_clean_checkpoint_list() to cleanup transaction's written-back
    If this call happens to remove all of them (and there were already some
    buffers), __journal_remove_checkpoint() will decide to free the transaction
    because it isn't (yet) a committing transaction and soon we fail some
    assertion - the transaction really isn't ready to be freed :).
    We change the check in __journal_remove_checkpoint() to free only a
    transaction in T_FINISHED state.  The locking there is subtle though (as
    everywhere in JBD ;().  We use j_list_lock to protect the check and a
    subsequent call to __journal_drop_transaction() and do the same in the end
    of journal_commit_transaction() which is the only place where a transaction
    can get to T_FINISHED state.
    Probably I'm too paranoid here and such locking is not really necessary -
    checkpoint lists are processed only from log_do_checkpoint() where a
    transaction must be already committed to be processed or from
    __journal_clean_checkpoint_list() where kjournald itself calls it and thus
    transaction cannot change state either.  Better be safe if something
    changes in future...
    Signed-off-by: Jan Kara <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
 fs/jbd2/checkpoint.c |   12 ++++++------
 fs/jbd2/commit.c     |    8 ++++----
 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 3fccde7..7e958c8 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -602,15 +602,15 @@ int __jbd2_journal_remove_checkpoint(struct journal_head 
         * There is one special case to worry about: if we have just pulled the
-        * buffer off a committing transaction's forget list, then even if the
-        * checkpoint list is empty, the transaction obviously cannot be
-        * dropped!
+        * buffer off a running or committing transaction's checkpoing list,
+        * then even if the checkpoint list is empty, the transaction obviously
+        * cannot be dropped!
-        * The locking here around j_committing_transaction is a bit sleazy.
+        * The locking here around t_state is a bit sleazy.
         * See the comment at the end of jbd2_journal_commit_transaction().
-       if (transaction == journal->j_committing_transaction) {
-               JBUFFER_TRACE(jh, "belongs to committing transaction");
+       if (transaction->t_state != T_FINISHED) {
+               JBUFFER_TRACE(jh, "belongs to running/committing transaction");
                goto out;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 6986f33..39b5cee 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -867,10 +867,10 @@ restart_loop:
-        * This is a bit sleazy.  We borrow j_list_lock to protect
-        * journal->j_committing_transaction in 
-        * Really, __jbd2_journal_remove_checkpoint should be using 
j_state_lock but
-        * it's a bit hassle to hold that across 
+        * This is a bit sleazy.  We use j_list_lock to protect transition
+        * of a transaction into T_FINISHED state and calling
+        * __jbd2_journal_drop_transaction(). Otherwise we could race with
+        * other checkpointing code processing the transaction...
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index d5f7cff..d861ffd 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -442,6 +442,8 @@ struct transaction_s
         * Transaction's current state
         * [no locking - only kjournald2 alters this]
+        * [j_list_lock] guards transition of a transaction into T_FINISHED
+        * state and subsequent call of __jbd2_journal_drop_transaction()
         * FIXME: needs barriers
         * KLUDGE: [use j_state_lock]
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to