The patch titled jbd: fix BUG in journal_commit_transaction() has been removed from the -mm tree. Its filename is jbd-fix-bug-in-journal_commit_transaction.patch This patch was dropped because it was merged into mainline or a subsystem tree ------------------------------------------------------ Subject: jbd: fix BUG in journal_commit_transaction() From: Jan Kara <jack@xxxxxxx> Fix possible assertion failure in journal_commit_transaction() on jh->b_next_transaction == NULL (when we are processing BJ_Forget list and buffer is not jbddirty). !jbddirty buffers can be placed on BJ_Forget list for example by journal_forget() or by __dispose_buffer() - generally such buffer means that it has been freed by this transaction. Freed buffers should not be reallocated until the transaction has committed (that's why we have the assertion there) but they *can* be reallocated when the transaction has already been committed to disk and we are just processing the BJ_Forget list (as soon as we remove b_committed_data from the bitmap bh, ext3 will be able to reallocate buffers freed by the committing transaction). So we have to also count with the case that the buffer has been reallocated and b_next_transaction has been already set. And one more subtle point: it can happen that we manage to reallocate the buffer and also mark it jbddirty. Then we also add the freed buffer to the checkpoint list of the committing trasaction. But that should do no harm. Non-jbddirty buffers should be filed to BJ_Reserved and not BJ_Metadata list. It can actually happen that we refile such buffers during the commit phase when we reallocate in the running transaction blocks deleted in committing transaction (and that can happen if the committing transaction already wrote all the data and is just cleaning up BJ_Forget list). Signed-off-by: Jan Kara <jack@xxxxxxx> Acked-by: "Stephen C. Tweedie" <sct@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- fs/jbd/commit.c | 21 ++++++++++++++++----- fs/jbd/transaction.c | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) diff -puN fs/jbd/commit.c~jbd-fix-bug-in-journal_commit_transaction fs/jbd/commit.c --- a/fs/jbd/commit.c~jbd-fix-bug-in-journal_commit_transaction +++ a/fs/jbd/commit.c @@ -790,11 +790,22 @@ restart_loop: jbd_unlock_bh_state(bh); } else { J_ASSERT_BH(bh, !buffer_dirty(bh)); - J_ASSERT_JH(jh, jh->b_next_transaction == NULL); - __journal_unfile_buffer(jh); - jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); /* needs a brelse */ - release_buffer_page(bh); + /* The buffer on BJ_Forget list and not jbddirty means + * it has been freed by this transaction and hence it + * could not have been reallocated until this + * transaction has committed. *BUT* it could be + * reallocated once we have written all the data to + * disk and before we process the buffer on BJ_Forget + * list. */ + JBUFFER_TRACE(jh, "refile or unfile freed buffer"); + __journal_refile_buffer(jh); + if (!jh->b_transaction) { + jbd_unlock_bh_state(bh); + /* needs a brelse */ + journal_remove_journal_head(bh); + release_buffer_page(bh); + } else + jbd_unlock_bh_state(bh); } cond_resched_lock(&journal->j_list_lock); } diff -puN fs/jbd/transaction.c~jbd-fix-bug-in-journal_commit_transaction fs/jbd/transaction.c --- a/fs/jbd/transaction.c~jbd-fix-bug-in-journal_commit_transaction +++ a/fs/jbd/transaction.c @@ -2038,7 +2038,8 @@ void __journal_refile_buffer(struct jour __journal_temp_unlink_buffer(jh); jh->b_transaction = jh->b_next_transaction; jh->b_next_transaction = NULL; - __journal_file_buffer(jh, jh->b_transaction, BJ_Metadata); + __journal_file_buffer(jh, jh->b_transaction, + was_dirty ? BJ_Metadata : BJ_Reserved); J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); if (was_dirty) _ Patches currently in -mm which might be from jack@xxxxxxx are origin.patch use-list_add_tail-instead-of-list_add.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html