Commit fba1fdee authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent 28a4dd1b
...@@ -442,7 +442,7 @@ int __log_space_left(journal_t *journal) ...@@ -442,7 +442,7 @@ int __log_space_left(journal_t *journal)
/* /*
* Called under j_state_lock. * 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; tid_t target = journal->j_commit_request;
......
...@@ -171,12 +171,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle) ...@@ -171,12 +171,12 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
*/ */
DEFINE_WAIT(wait); 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); 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, prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
TASK_UNINTERRUPTIBLE); TASK_UNINTERRUPTIBLE);
log_start_commit(journal, transaction); __log_start_commit(journal, transaction);
spin_unlock(&journal->j_state_lock);
schedule(); schedule();
finish_wait(&journal->j_wait_transaction_locked, &wait); finish_wait(&journal->j_wait_transaction_locked, &wait);
goto repeat; goto repeat;
......
...@@ -991,6 +991,7 @@ extern void journal_switch_revoke_table(journal_t *journal); ...@@ -991,6 +991,7 @@ extern void journal_switch_revoke_table(journal_t *journal);
int __log_space_left(journal_t *); /* Called with journal locked */ 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 tid_t __log_start_commit(journal_t *, transaction_t *);
extern int log_wait_commit (journal_t *, tid_t); extern int log_wait_commit (journal_t *, tid_t);
extern int log_do_checkpoint (journal_t *, int); extern int log_do_checkpoint (journal_t *, int);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment