aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jbd')
-rw-r--r--fs/jbd/journal.c1
-rw-r--r--fs/jbd/transaction.c38
2 files changed, 22 insertions, 17 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index fea8dd661d2b..1656dc2e6a08 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -721,7 +721,6 @@ static journal_t * journal_init_common (void)
721 init_waitqueue_head(&journal->j_wait_checkpoint); 721 init_waitqueue_head(&journal->j_wait_checkpoint);
722 init_waitqueue_head(&journal->j_wait_commit); 722 init_waitqueue_head(&journal->j_wait_commit);
723 init_waitqueue_head(&journal->j_wait_updates); 723 init_waitqueue_head(&journal->j_wait_updates);
724 mutex_init(&journal->j_barrier);
725 mutex_init(&journal->j_checkpoint_mutex); 724 mutex_init(&journal->j_checkpoint_mutex);
726 spin_lock_init(&journal->j_revoke_lock); 725 spin_lock_init(&journal->j_revoke_lock);
727 spin_lock_init(&journal->j_list_lock); 726 spin_lock_init(&journal->j_list_lock);
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 7e59c6e66f9b..7fce94b04bc3 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -426,17 +426,34 @@ int journal_restart(handle_t *handle, int nblocks)
426 * void journal_lock_updates () - establish a transaction barrier. 426 * void journal_lock_updates () - establish a transaction barrier.
427 * @journal: Journal to establish a barrier on. 427 * @journal: Journal to establish a barrier on.
428 * 428 *
429 * This locks out any further updates from being started, and blocks 429 * This locks out any further updates from being started, and blocks until all
430 * until all existing updates have completed, returning only once the 430 * existing updates have completed, returning only once the journal is in a
431 * journal is in a quiescent state with no updates running. 431 * quiescent state with no updates running.
432 * 432 *
433 * The journal lock should not be held on entry. 433 * We do not use simple mutex for synchronization as there are syscalls which
434 * want to return with filesystem locked and that trips up lockdep. Also
435 * hibernate needs to lock filesystem but locked mutex then blocks hibernation.
436 * Since locking filesystem is rare operation, we use simple counter and
437 * waitqueue for locking.
434 */ 438 */
435void journal_lock_updates(journal_t *journal) 439void journal_lock_updates(journal_t *journal)
436{ 440{
437 DEFINE_WAIT(wait); 441 DEFINE_WAIT(wait);
438 442
443wait:
444 /* Wait for previous locked operation to finish */
445 wait_event(journal->j_wait_transaction_locked,
446 journal->j_barrier_count == 0);
447
439 spin_lock(&journal->j_state_lock); 448 spin_lock(&journal->j_state_lock);
449 /*
450 * Check reliably under the lock whether we are the ones winning the race
451 * and locking the journal
452 */
453 if (journal->j_barrier_count > 0) {
454 spin_unlock(&journal->j_state_lock);
455 goto wait;
456 }
440 ++journal->j_barrier_count; 457 ++journal->j_barrier_count;
441 458
442 /* Wait until there are no running updates */ 459 /* Wait until there are no running updates */
@@ -460,14 +477,6 @@ void journal_lock_updates(journal_t *journal)
460 spin_lock(&journal->j_state_lock); 477 spin_lock(&journal->j_state_lock);
461 } 478 }
462 spin_unlock(&journal->j_state_lock); 479 spin_unlock(&journal->j_state_lock);
463
464 /*
465 * We have now established a barrier against other normal updates, but
466 * we also need to barrier against other journal_lock_updates() calls
467 * to make sure that we serialise special journal-locked operations
468 * too.
469 */
470 mutex_lock(&journal->j_barrier);
471} 480}
472 481
473/** 482/**
@@ -475,14 +484,11 @@ void journal_lock_updates(journal_t *journal)
475 * @journal: Journal to release the barrier on. 484 * @journal: Journal to release the barrier on.
476 * 485 *
477 * Release a transaction barrier obtained with journal_lock_updates(). 486 * Release a transaction barrier obtained with journal_lock_updates().
478 *
479 * Should be called without the journal lock held.
480 */ 487 */
481void journal_unlock_updates (journal_t *journal) 488void journal_unlock_updates (journal_t *journal)
482{ 489{
483 J_ASSERT(journal->j_barrier_count != 0); 490 J_ASSERT(journal->j_barrier_count != 0);
484 491
485 mutex_unlock(&journal->j_barrier);
486 spin_lock(&journal->j_state_lock); 492 spin_lock(&journal->j_state_lock);
487 --journal->j_barrier_count; 493 --journal->j_barrier_count;
488 spin_unlock(&journal->j_state_lock); 494 spin_unlock(&journal->j_state_lock);