From 269c217537f09581daeb3e1acf15f3a42b2ea35a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 6 Sep 2005 15:19:09 -0700 Subject: [PATCH] --- yaml --- r: 7487 b: refs/heads/master c: e6c9f5c1888097c936334bf9740024520ca47b8e h: refs/heads/master i: 7485: 47dcc1f83f36d59ea8720e9df759028b442b12c7 7483: 4218c7a59ab7c023ddad8e067521faaf4c31ef15 7479: d81d89144db3f7fa8c41293792fd4eaa166ac40f 7471: 816a7212a73ab17048c48640362d2b538179c2fe 7455: a553a0e3d9b373f3a7f3d23825eb2d5860768541 7423: 6decc40e63e8bfa2fb56ef482817081a20f0a970 v: v3 --- [refs] | 2 +- trunk/fs/jbd/commit.c | 34 ++++++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index 777b59d457ea..bba3e0c856bf 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cbf0d27a131639f4f3e4faa94373c5c6f89f8f07 +refs/heads/master: e6c9f5c1888097c936334bf9740024520ca47b8e diff --git a/trunk/fs/jbd/commit.c b/trunk/fs/jbd/commit.c index dac720c837ab..9d0494dcc571 100644 --- a/trunk/fs/jbd/commit.c +++ b/trunk/fs/jbd/commit.c @@ -720,11 +720,17 @@ void journal_commit_transaction(journal_t *journal) J_ASSERT(commit_transaction->t_log_list == NULL); restart_loop: + /* + * As there are other places (journal_unmap_buffer()) adding buffers + * to this list we have to be careful and hold the j_list_lock. + */ + spin_lock(&journal->j_list_lock); while (commit_transaction->t_forget) { transaction_t *cp_transaction; struct buffer_head *bh; jh = commit_transaction->t_forget; + spin_unlock(&journal->j_list_lock); bh = jh2bh(jh); jbd_lock_bh_state(bh); J_ASSERT_JH(jh, jh->b_transaction == commit_transaction || @@ -792,9 +798,25 @@ void journal_commit_transaction(journal_t *journal) journal_remove_journal_head(bh); /* needs a brelse */ release_buffer_page(bh); } + cond_resched_lock(&journal->j_list_lock); + } + spin_unlock(&journal->j_list_lock); + /* + * This is a bit sleazy. We borrow j_list_lock to protect + * journal->j_committing_transaction in __journal_remove_checkpoint. + * Really, __journal_remove_checkpoint should be using j_state_lock but + * it's a bit hassle to hold that across __journal_remove_checkpoint + */ + spin_lock(&journal->j_state_lock); + spin_lock(&journal->j_list_lock); + /* + * Now recheck if some buffers did not get attached to the transaction + * while the lock was dropped... + */ + if (commit_transaction->t_forget) { spin_unlock(&journal->j_list_lock); - if (cond_resched()) - goto restart_loop; + spin_unlock(&journal->j_state_lock); + goto restart_loop; } /* Done with this transaction! */ @@ -803,14 +825,6 @@ void journal_commit_transaction(journal_t *journal) J_ASSERT(commit_transaction->t_state == T_COMMIT); - /* - * This is a bit sleazy. We borrow j_list_lock to protect - * journal->j_committing_transaction in __journal_remove_checkpoint. - * Really, __jornal_remove_checkpoint should be using j_state_lock but - * it's a bit hassle to hold that across __journal_remove_checkpoint - */ - spin_lock(&journal->j_state_lock); - spin_lock(&journal->j_list_lock); commit_transaction->t_state = T_FINISHED; J_ASSERT(commit_transaction == journal->j_committing_transaction); journal->j_commit_sequence = commit_transaction->t_tid;