From 1e498c6f81cc91ce9daa3bd7d6cc1e8bf8e6f9b7 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 22 Dec 2011 14:52:21 +0100 Subject: [PATCH] --- yaml --- r: 281456 b: refs/heads/master c: 0048278552e9752fd578c3d8deee756987c10873 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/jbd/journal.c | 1 - trunk/fs/jbd/transaction.c | 38 ++++++++++++++++++++++---------------- trunk/include/linux/jbd.h | 4 ---- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/[refs] b/[refs] index ae4df8590f94..996517ba038c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a9e36da655e54545c3289b2a0700b5c443de0edd +refs/heads/master: 0048278552e9752fd578c3d8deee756987c10873 diff --git a/trunk/fs/jbd/journal.c b/trunk/fs/jbd/journal.c index fea8dd661d2b..1656dc2e6a08 100644 --- a/trunk/fs/jbd/journal.c +++ b/trunk/fs/jbd/journal.c @@ -721,7 +721,6 @@ static journal_t * journal_init_common (void) init_waitqueue_head(&journal->j_wait_checkpoint); init_waitqueue_head(&journal->j_wait_commit); init_waitqueue_head(&journal->j_wait_updates); - mutex_init(&journal->j_barrier); mutex_init(&journal->j_checkpoint_mutex); spin_lock_init(&journal->j_revoke_lock); spin_lock_init(&journal->j_list_lock); diff --git a/trunk/fs/jbd/transaction.c b/trunk/fs/jbd/transaction.c index 7e59c6e66f9b..7fce94b04bc3 100644 --- a/trunk/fs/jbd/transaction.c +++ b/trunk/fs/jbd/transaction.c @@ -426,17 +426,34 @@ int journal_restart(handle_t *handle, int nblocks) * void journal_lock_updates () - establish a transaction barrier. * @journal: Journal to establish a barrier on. * - * This locks out any further updates from being started, and blocks - * until all existing updates have completed, returning only once the - * journal is in a quiescent state with no updates running. - * - * The journal lock should not be held on entry. + * This locks out any further updates from being started, and blocks until all + * existing updates have completed, returning only once the journal is in a + * quiescent state with no updates running. + * + * We do not use simple mutex for synchronization as there are syscalls which + * want to return with filesystem locked and that trips up lockdep. Also + * hibernate needs to lock filesystem but locked mutex then blocks hibernation. + * Since locking filesystem is rare operation, we use simple counter and + * waitqueue for locking. */ void journal_lock_updates(journal_t *journal) { DEFINE_WAIT(wait); +wait: + /* Wait for previous locked operation to finish */ + wait_event(journal->j_wait_transaction_locked, + journal->j_barrier_count == 0); + spin_lock(&journal->j_state_lock); + /* + * Check reliably under the lock whether we are the ones winning the race + * and locking the journal + */ + if (journal->j_barrier_count > 0) { + spin_unlock(&journal->j_state_lock); + goto wait; + } ++journal->j_barrier_count; /* Wait until there are no running updates */ @@ -460,14 +477,6 @@ void journal_lock_updates(journal_t *journal) spin_lock(&journal->j_state_lock); } spin_unlock(&journal->j_state_lock); - - /* - * We have now established a barrier against other normal updates, but - * we also need to barrier against other journal_lock_updates() calls - * to make sure that we serialise special journal-locked operations - * too. - */ - mutex_lock(&journal->j_barrier); } /** @@ -475,14 +484,11 @@ void journal_lock_updates(journal_t *journal) * @journal: Journal to release the barrier on. * * Release a transaction barrier obtained with journal_lock_updates(). - * - * Should be called without the journal lock held. */ void journal_unlock_updates (journal_t *journal) { J_ASSERT(journal->j_barrier_count != 0); - mutex_unlock(&journal->j_barrier); spin_lock(&journal->j_state_lock); --journal->j_barrier_count; spin_unlock(&journal->j_state_lock); diff --git a/trunk/include/linux/jbd.h b/trunk/include/linux/jbd.h index 492cc12244fd..d211732b9e99 100644 --- a/trunk/include/linux/jbd.h +++ b/trunk/include/linux/jbd.h @@ -497,7 +497,6 @@ struct transaction_s * @j_format_version: Version of the superblock format * @j_state_lock: Protect the various scalars in the journal * @j_barrier_count: Number of processes waiting to create a barrier lock - * @j_barrier: The barrier lock itself * @j_running_transaction: The current running transaction.. * @j_committing_transaction: the transaction we are pushing to disk * @j_checkpoint_transactions: a linked circular list of all transactions @@ -580,9 +579,6 @@ struct journal_s */ int j_barrier_count; - /* The barrier lock itself */ - struct mutex j_barrier; - /* * Transactions: The current running transaction... * [j_state_lock] [caller holding open handle]