implement the designed locking around journal->j_commit_sequence. fs/jbd/journal.c | 30 ++++++++++++++++++++++-------- 1 files changed, 22 insertions(+), 8 deletions(-) diff -puN fs/jbd/journal.c~jbd-220-j_commit_sequence-locking fs/jbd/journal.c --- 25/fs/jbd/journal.c~jbd-220-j_commit_sequence-locking 2003-05-25 00:21:31.000000000 -0700 +++ 25-akpm/fs/jbd/journal.c 2003-05-25 00:21:34.000000000 -0700 @@ -162,27 +162,36 @@ int kjournald(void *arg) jbd_debug(1, "commit_sequence=%d, commit_request=%d\n", journal->j_commit_sequence, journal->j_commit_request); + spin_lock(&journal->j_state_lock); if (journal->j_commit_sequence != journal->j_commit_request) { jbd_debug(1, "OK, requests differ\n"); if (journal->j_commit_timer_active) { journal->j_commit_timer_active = 0; del_timer(journal->j_commit_timer); } - + spin_unlock(&journal->j_state_lock); journal_commit_transaction(journal); continue; } + spin_unlock(&journal->j_state_lock); wake_up(&journal->j_wait_done_commit); - if (current->flags & PF_FREEZE) { /* The simpler the better. Flushing journal isn't a - good idea, because that depends on threads that - may be already stopped. */ + if (current->flags & PF_FREEZE) { + /* + * The simpler the better. Flushing journal isn't a + * good idea, because that depends on threads that may + * be already stopped. + */ jbd_debug(1, "Now suspending kjournald\n"); refrigerator(PF_IOTHREAD); jbd_debug(1, "Resuming kjournald\n"); - } else /* we assume on resume that commits are already there, - so we don't sleep */ + } else { + /* + * We assume on resume that commits are already there, + * so we don't sleep + */ interruptible_sleep_on(&journal->j_wait_commit); + } jbd_debug(1, "kjournald wakes\n"); @@ -475,7 +484,7 @@ tid_t log_start_commit(journal_t *journa * Wait for a specified commit to complete. * The caller may not hold the journal lock. */ -int log_wait_commit (journal_t *journal, tid_t tid) +int log_wait_commit(journal_t *journal, tid_t tid) { int err = 0; @@ -489,12 +498,17 @@ int log_wait_commit (journal_t *journal, } unlock_journal(journal); #endif + spin_lock(&journal->j_state_lock); while (tid_gt(tid, journal->j_commit_sequence)) { jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n", tid, journal->j_commit_sequence); wake_up(&journal->j_wait_commit); - sleep_on(&journal->j_wait_done_commit); + spin_unlock(&journal->j_state_lock); + wait_event(journal->j_wait_done_commit, + !tid_gt(tid, journal->j_commit_sequence)); + spin_lock(&journal->j_state_lock); } + spin_unlock(&journal->j_state_lock); if (unlikely(is_journal_aborted(journal))) { printk(KERN_EMERG "journal commit I/O error\n"); _