diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:51:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:51:21 -0500 |
commit | ac69e0928054ff29a5049902fb477f9c7605c773 (patch) | |
tree | 05be6b9285186823452e0adeffe40e1dfee6e354 /fs/jbd | |
parent | 9e203936eac786f9268d6a13e6442d2accef1829 (diff) | |
parent | 302bf2f3259948c93361d501b04a5ed69c3bd4f8 (diff) |
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
Diffstat (limited to 'fs/jbd')
-rw-r--r-- | fs/jbd/commit.c | 6 | ||||
-rw-r--r-- | fs/jbd/journal.c | 1 | ||||
-rw-r--r-- | fs/jbd/revoke.c | 34 | ||||
-rw-r--r-- | fs/jbd/transaction.c | 38 |
4 files changed, 62 insertions, 17 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 8799207df058..f2b9a571f4cf 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -392,6 +392,12 @@ void journal_commit_transaction(journal_t *journal) | |||
392 | jbd_debug (3, "JBD: commit phase 1\n"); | 392 | jbd_debug (3, "JBD: commit phase 1\n"); |
393 | 393 | ||
394 | /* | 394 | /* |
395 | * Clear revoked flag to reflect there is no revoked buffers | ||
396 | * in the next transaction which is going to be started. | ||
397 | */ | ||
398 | journal_clear_buffer_revoked_flags(journal); | ||
399 | |||
400 | /* | ||
395 | * Switch to a new revoke table. | 401 | * Switch to a new revoke table. |
396 | */ | 402 | */ |
397 | journal_switch_revoke_table(journal); | 403 | journal_switch_revoke_table(journal); |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index a96cff0c5f1d..59c09f9541b5 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/revoke.c b/fs/jbd/revoke.c index 305a90763154..25c713e7071c 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c | |||
@@ -47,6 +47,10 @@ | |||
47 | * overwriting the new data. We don't even need to clear the revoke | 47 | * overwriting the new data. We don't even need to clear the revoke |
48 | * bit here. | 48 | * bit here. |
49 | * | 49 | * |
50 | * We cache revoke status of a buffer in the current transaction in b_states | ||
51 | * bits. As the name says, revokevalid flag indicates that the cached revoke | ||
52 | * status of a buffer is valid and we can rely on the cached status. | ||
53 | * | ||
50 | * Revoke information on buffers is a tri-state value: | 54 | * Revoke information on buffers is a tri-state value: |
51 | * | 55 | * |
52 | * RevokeValid clear: no cached revoke status, need to look it up | 56 | * 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) | |||
479 | return did_revoke; | 483 | return did_revoke; |
480 | } | 484 | } |
481 | 485 | ||
486 | /* | ||
487 | * journal_clear_revoked_flags clears revoked flag of buffers in | ||
488 | * revoke table to reflect there is no revoked buffer in the next | ||
489 | * transaction which is going to be started. | ||
490 | */ | ||
491 | void journal_clear_buffer_revoked_flags(journal_t *journal) | ||
492 | { | ||
493 | struct jbd_revoke_table_s *revoke = journal->j_revoke; | ||
494 | int i = 0; | ||
495 | |||
496 | for (i = 0; i < revoke->hash_size; i++) { | ||
497 | struct list_head *hash_list; | ||
498 | struct list_head *list_entry; | ||
499 | hash_list = &revoke->hash_table[i]; | ||
500 | |||
501 | list_for_each(list_entry, hash_list) { | ||
502 | struct jbd_revoke_record_s *record; | ||
503 | struct buffer_head *bh; | ||
504 | record = (struct jbd_revoke_record_s *)list_entry; | ||
505 | bh = __find_get_block(journal->j_fs_dev, | ||
506 | record->blocknr, | ||
507 | journal->j_blocksize); | ||
508 | if (bh) { | ||
509 | clear_buffer_revoked(bh); | ||
510 | __brelse(bh); | ||
511 | } | ||
512 | } | ||
513 | } | ||
514 | } | ||
515 | |||
482 | /* journal_switch_revoke table select j_revoke for next transaction | 516 | /* journal_switch_revoke table select j_revoke for next transaction |
483 | * we do not want to suspend any processing until all revokes are | 517 | * we do not want to suspend any processing until all revokes are |
484 | * written -bzzz | 518 | * written -bzzz |
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); |