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

[PATCH] JBD: implement j_commit_request locking

Impement the designed locking around journal->j_commit_request.
parent 6b65bc1f
...@@ -152,63 +152,91 @@ int kjournald(void *arg) ...@@ -152,63 +152,91 @@ int kjournald(void *arg)
printk(KERN_INFO "kjournald starting. Commit interval %ld seconds\n", printk(KERN_INFO "kjournald starting. Commit interval %ld seconds\n",
journal->j_commit_interval / HZ); journal->j_commit_interval / HZ);
lock_kernel();
list_add(&journal->j_all_journals, &all_journals); list_add(&journal->j_all_journals, &all_journals);
unlock_kernel();
/* And now, wait forever for commit wakeup events. */ /*
while (1) { * And now, wait forever for commit wakeup events.
if (journal->j_flags & JFS_UNMOUNT) */
break; spin_lock(&journal->j_state_lock);
jbd_debug(1, "commit_sequence=%d, commit_request=%d\n", loop:
journal->j_commit_sequence, journal->j_commit_request); 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) {
if (journal->j_commit_sequence != journal->j_commit_request) { jbd_debug(1, "OK, requests differ\n");
jbd_debug(1, "OK, requests differ\n"); if (journal->j_commit_timer_active) {
if (journal->j_commit_timer_active) { journal->j_commit_timer_active = 0;
journal->j_commit_timer_active = 0; del_timer(journal->j_commit_timer);
del_timer(journal->j_commit_timer);
}
spin_unlock(&journal->j_state_lock);
journal_commit_transaction(journal);
continue;
} }
spin_unlock(&journal->j_state_lock); spin_unlock(&journal->j_state_lock);
journal_commit_transaction(journal);
spin_lock(&journal->j_state_lock);
goto loop;
}
wake_up(&journal->j_wait_done_commit); wake_up(&journal->j_wait_done_commit);
if (current->flags & PF_FREEZE) { if (current->flags & PF_FREEZE) {
/* /*
* The simpler the better. Flushing journal isn't a * The simpler the better. Flushing journal isn't a
* good idea, because that depends on threads that may * good idea, because that depends on threads that may
* be already stopped. * be already stopped.
*/ */
jbd_debug(1, "Now suspending kjournald\n"); jbd_debug(1, "Now suspending kjournald\n");
refrigerator(PF_IOTHREAD); spin_unlock(&journal->j_state_lock);
jbd_debug(1, "Resuming kjournald\n"); refrigerator(PF_IOTHREAD);
} else { spin_lock(&journal->j_state_lock);
/* jbd_debug(1, "Resuming kjournald\n");
* We assume on resume that commits are already there, } else {
* so we don't sleep /*
*/ * We assume on resume that commits are already there,
interruptible_sleep_on(&journal->j_wait_commit); * so we don't sleep
*/
DEFINE_WAIT(wait);
int should_sleep = 1;
prepare_to_wait(&journal->j_wait_commit, &wait,
TASK_INTERRUPTIBLE);
if (journal->j_commit_sequence != journal->j_commit_request)
should_sleep = 0;
transaction = journal->j_running_transaction;
if (transaction && time_after_eq(jiffies,
transaction->t_expires))
should_sleep = 0;
if (should_sleep) {
spin_unlock(&journal->j_state_lock);
schedule();
spin_lock(&journal->j_state_lock);
} }
finish_wait(&journal->j_wait_commit, &wait);
}
jbd_debug(1, "kjournald wakes\n"); jbd_debug(1, "kjournald wakes\n");
/* Were we woken up by a commit wakeup event? */ /*
if ((transaction = journal->j_running_transaction) != NULL && * Were we woken up by a commit wakeup event?
time_after_eq(jiffies, transaction->t_expires)) { */
journal->j_commit_request = transaction->t_tid; transaction = journal->j_running_transaction;
jbd_debug(1, "woke because of timeout\n"); if (transaction && time_after_eq(jiffies, transaction->t_expires)) {
} journal->j_commit_request = transaction->t_tid;
jbd_debug(1, "woke because of timeout\n");
} }
if (!(journal->j_flags & JFS_UNMOUNT))
goto loop;
if (journal->j_commit_timer_active) { if (journal->j_commit_timer_active) {
journal->j_commit_timer_active = 0; journal->j_commit_timer_active = 0;
del_timer_sync(journal->j_commit_timer); del_timer_sync(journal->j_commit_timer);
} }
spin_unlock(&journal->j_state_lock);
lock_kernel();
list_del(&journal->j_all_journals); list_del(&journal->j_all_journals);
unlock_kernel();
journal->j_task = NULL; journal->j_task = NULL;
wake_up(&journal->j_wait_done_commit); wake_up(&journal->j_wait_done_commit);
...@@ -430,7 +458,7 @@ int __log_space_left(journal_t *journal) ...@@ -430,7 +458,7 @@ int __log_space_left(journal_t *journal)
} }
/* /*
* This function must be non-allocating for PF_MEMALLOC tasks * Called under j_state_lock.
*/ */
static tid_t __log_start_commit(journal_t *journal, transaction_t *transaction) static tid_t __log_start_commit(journal_t *journal, transaction_t *transaction)
{ {
...@@ -491,11 +519,13 @@ int log_wait_commit(journal_t *journal, tid_t tid) ...@@ -491,11 +519,13 @@ int log_wait_commit(journal_t *journal, tid_t tid)
lock_kernel(); lock_kernel();
#ifdef CONFIG_JBD_DEBUG #ifdef CONFIG_JBD_DEBUG
lock_journal(journal); lock_journal(journal);
spin_lock(&journal->j_state_lock);
if (!tid_geq(journal->j_commit_request, tid)) { if (!tid_geq(journal->j_commit_request, tid)) {
printk(KERN_EMERG printk(KERN_EMERG
"%s: error: j_commit_request=%d, tid=%d\n", "%s: error: j_commit_request=%d, tid=%d\n",
__FUNCTION__, journal->j_commit_request, tid); __FUNCTION__, journal->j_commit_request, tid);
} }
spin_unlock(&journal->j_state_lock);
unlock_journal(journal); unlock_journal(journal);
#endif #endif
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
......
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