]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] JBD: fix log_start_commit race
authorAndrew Morton <akpm@digeo.com>
Wed, 18 Jun 2003 01:31:15 +0000 (18:31 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Wed, 18 Jun 2003 01:31:15 +0000 (18:31 -0700)
In start_this_handle() the caller does not have a handle ref pinning the
transaction open, and so the call to log_start_commit() is racy because some
other CPU could take the transaction into commit state independently.

Fix that by holding j_state_lock (which pins j_running_transaction) across
the log_start_commit() call.

fs/jbd/journal.c
fs/jbd/transaction.c
include/linux/jbd.h

index fc40cff80ac20543ec2176554e725e54bc89bbd6..4889809093198a68f718a7ce96df45dc6ef28113 100644 (file)
@@ -442,7 +442,7 @@ int __log_space_left(journal_t *journal)
 /*
  * Called under j_state_lock.
  */
-static tid_t __log_start_commit(journal_t *journal, transaction_t *transaction)
+tid_t __log_start_commit(journal_t *journal, transaction_t *transaction)
 {
        tid_t target = journal->j_commit_request;
 
index f42f25429858c6404acee1ea7c04189961179e17..5a3461dd8c05f98ed672f2d3e09221d6869a83be 100644 (file)
@@ -171,12 +171,12 @@ repeat:
                 */
                DEFINE_WAIT(wait);
 
-               spin_unlock(&transaction->t_handle_lock);
-               spin_unlock(&journal->j_state_lock);
                jbd_debug(2, "Handle %p starting new commit...\n", handle);
+               spin_unlock(&transaction->t_handle_lock);
                prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
                                TASK_UNINTERRUPTIBLE);
-               log_start_commit(journal, transaction);
+               __log_start_commit(journal, transaction);
+               spin_unlock(&journal->j_state_lock);
                schedule();
                finish_wait(&journal->j_wait_transaction_locked, &wait);
                goto repeat;
index e0501a317e316cae0e7c1108b63a87d59df51fe3..567c835eb73eb81dd85455a04df960884e436e35 100644 (file)
@@ -991,6 +991,7 @@ extern void journal_switch_revoke_table(journal_t *journal);
 
 int __log_space_left(journal_t *); /* Called with journal locked */
 extern tid_t   log_start_commit (journal_t *, transaction_t *);
+extern tid_t   __log_start_commit(journal_t *, transaction_t *);
 extern int     log_wait_commit (journal_t *, tid_t);
 extern int     log_do_checkpoint (journal_t *, int);