diff options
Diffstat (limited to 'fs/jbd')
-rw-r--r-- | fs/jbd/journal.c | 1 | ||||
-rw-r--r-- | fs/jbd/transaction.c | 38 |
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 | */ |
435 | void journal_lock_updates(journal_t *journal) | 439 | void journal_lock_updates(journal_t *journal) |
436 | { | 440 | { |
437 | DEFINE_WAIT(wait); | 441 | DEFINE_WAIT(wait); |
438 | 442 | ||
443 | wait: | ||
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 | */ |
481 | void journal_unlock_updates (journal_t *journal) | 488 | void 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); |