diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-06-17 18:31:15 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-06-17 18:31:15 -0700 |
| commit | fba1fdeecf6a0ddc41277bb200beec5ad89f8c61 (patch) | |
| tree | 41e78427a68e9d608fad46c3c41476641f99e9c9 | |
| parent | 28a4dd1ba782d5b0f27dca9632296a452c204286 (diff) | |
[PATCH] JBD: fix log_start_commit race
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.
| -rw-r--r-- | fs/jbd/journal.c | 2 | ||||
| -rw-r--r-- | fs/jbd/transaction.c | 6 | ||||
| -rw-r--r-- | include/linux/jbd.h | 1 |
3 files changed, 5 insertions, 4 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index fc40cff80ac2..488980909319 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -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; diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index f42f25429858..5a3461dd8c05 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -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; diff --git a/include/linux/jbd.h b/include/linux/jbd.h index e0501a317e31..567c835eb73e 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -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); |
