Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  ext2/3/4: delete unneeded includes of module.h
  ext{3,4}: Fix potential race when setversion ioctl updates inode
  udf: Mark LVID buffer as uptodate before marking it dirty
  ext3: Don't warn from writepage when readonly inode is spotted after error
  jbd: Remove j_barrier mutex
  reiserfs: Force inode evictions before umount to avoid crash
  reiserfs: Fix quota mount option parsing
  udf: Treat symlink component of type 2 as /
  udf: Fix deadlock when converting file from in-ICB one to normal one
  udf: Cleanup calling convention of inode_getblk()
  ext2: Fix error handling on inode bitmap corruption
  ext3: Fix error handling on inode bitmap corruption
  ext3: replace ll_rw_block with other functions
  ext3: NULL dereference in ext3_evict_inode()
  jbd: clear revoked flag on buffers before a new transaction started
  ext3: call ext3_mark_recovery_complete() when recovery is really needed
This commit is contained in:
Linus Torvalds 2012-01-09 12:51:21 -08:00
commit ac69e09280
35 changed files with 201 additions and 111 deletions

View file

@ -391,6 +391,12 @@ void journal_commit_transaction(journal_t *journal)
jbd_debug (3, "JBD: commit phase 1\n");
/*
* Clear revoked flag to reflect there is no revoked buffers
* in the next transaction which is going to be started.
*/
journal_clear_buffer_revoked_flags(journal);
/*
* Switch to a new revoke table.
*/

View file

@ -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);

View file

@ -47,6 +47,10 @@
* overwriting the new data. We don't even need to clear the revoke
* bit here.
*
* We cache revoke status of a buffer in the current transaction in b_states
* bits. As the name says, revokevalid flag indicates that the cached revoke
* status of a buffer is valid and we can rely on the cached status.
*
* Revoke information on buffers is a tri-state value:
*
* RevokeValid clear: no cached revoke status, need to look it up
@ -479,6 +483,36 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
return did_revoke;
}
/*
* journal_clear_revoked_flags clears revoked flag of buffers in
* revoke table to reflect there is no revoked buffer in the next
* transaction which is going to be started.
*/
void journal_clear_buffer_revoked_flags(journal_t *journal)
{
struct jbd_revoke_table_s *revoke = journal->j_revoke;
int i = 0;
for (i = 0; i < revoke->hash_size; i++) {
struct list_head *hash_list;
struct list_head *list_entry;
hash_list = &revoke->hash_table[i];
list_for_each(list_entry, hash_list) {
struct jbd_revoke_record_s *record;
struct buffer_head *bh;
record = (struct jbd_revoke_record_s *)list_entry;
bh = __find_get_block(journal->j_fs_dev,
record->blocknr,
journal->j_blocksize);
if (bh) {
clear_buffer_revoked(bh);
__brelse(bh);
}
}
}
}
/* journal_switch_revoke table select j_revoke for next transaction
* we do not want to suspend any processing until all revokes are
* written -bzzz

View file

@ -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.
* 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.
* 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);