aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2011-12-22 08:52:21 -0500
committerJan Kara <jack@suse.cz>2012-01-09 07:52:09 -0500
commit0048278552e9752fd578c3d8deee756987c10873 (patch)
tree0931a7ff6aa5c388eb40e2a97fdcebe59bbae337 /fs/jbd
parenta9e36da655e54545c3289b2a0700b5c443de0edd (diff)
jbd: Remove j_barrier mutex
j_barrier mutex is used for serializing different journal lock operations. The problem with it is that e.g. FIFREEZE ioctl results in process leaving kernel with j_barrier mutex held which makes lockdep freak out. Also hibernation code wants to freeze filesystem but it cannot do so because it then cannot hibernate the system because of mutex being locked. So we remove j_barrier mutex and use direct wait on j_barrier_count instead. Since locking journal is a rare operation we don't have to care about fairness or such things. CC: Andrew Morton <akpm@linux-foundation.org> Acked-by: Joel Becker <jlbec@evilplan.org> Signed-off-by: Jan Kara <jack@suse.cz>
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);