diff options
Diffstat (limited to 'fs/jbd2')
| -rw-r--r-- | fs/jbd2/commit.c | 22 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 58 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 22 |
3 files changed, 87 insertions, 15 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 29148a81c783..7f21cf3aaf92 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -219,7 +219,6 @@ static int journal_submit_data_buffers(journal_t *journal, | |||
| 219 | ret = err; | 219 | ret = err; |
| 220 | spin_lock(&journal->j_list_lock); | 220 | spin_lock(&journal->j_list_lock); |
| 221 | J_ASSERT(jinode->i_transaction == commit_transaction); | 221 | J_ASSERT(jinode->i_transaction == commit_transaction); |
| 222 | commit_transaction->t_flushed_data_blocks = 1; | ||
| 223 | clear_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); | 222 | clear_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); |
| 224 | smp_mb__after_clear_bit(); | 223 | smp_mb__after_clear_bit(); |
| 225 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); | 224 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); |
| @@ -672,12 +671,16 @@ start_journal_io: | |||
| 672 | err = 0; | 671 | err = 0; |
| 673 | } | 672 | } |
| 674 | 673 | ||
| 674 | write_lock(&journal->j_state_lock); | ||
| 675 | J_ASSERT(commit_transaction->t_state == T_COMMIT); | ||
| 676 | commit_transaction->t_state = T_COMMIT_DFLUSH; | ||
| 677 | write_unlock(&journal->j_state_lock); | ||
| 675 | /* | 678 | /* |
| 676 | * If the journal is not located on the file system device, | 679 | * If the journal is not located on the file system device, |
| 677 | * then we must flush the file system device before we issue | 680 | * then we must flush the file system device before we issue |
| 678 | * the commit record | 681 | * the commit record |
| 679 | */ | 682 | */ |
| 680 | if (commit_transaction->t_flushed_data_blocks && | 683 | if (commit_transaction->t_need_data_flush && |
| 681 | (journal->j_fs_dev != journal->j_dev) && | 684 | (journal->j_fs_dev != journal->j_dev) && |
| 682 | (journal->j_flags & JBD2_BARRIER)) | 685 | (journal->j_flags & JBD2_BARRIER)) |
| 683 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); | 686 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); |
| @@ -754,8 +757,13 @@ wait_for_iobuf: | |||
| 754 | required. */ | 757 | required. */ |
| 755 | JBUFFER_TRACE(jh, "file as BJ_Forget"); | 758 | JBUFFER_TRACE(jh, "file as BJ_Forget"); |
| 756 | jbd2_journal_file_buffer(jh, commit_transaction, BJ_Forget); | 759 | jbd2_journal_file_buffer(jh, commit_transaction, BJ_Forget); |
| 757 | /* Wake up any transactions which were waiting for this | 760 | /* |
| 758 | IO to complete */ | 761 | * Wake up any transactions which were waiting for this IO to |
| 762 | * complete. The barrier must be here so that changes by | ||
| 763 | * jbd2_journal_file_buffer() take effect before wake_up_bit() | ||
| 764 | * does the waitqueue check. | ||
| 765 | */ | ||
| 766 | smp_mb(); | ||
| 759 | wake_up_bit(&bh->b_state, BH_Unshadow); | 767 | wake_up_bit(&bh->b_state, BH_Unshadow); |
| 760 | JBUFFER_TRACE(jh, "brelse shadowed buffer"); | 768 | JBUFFER_TRACE(jh, "brelse shadowed buffer"); |
| 761 | __brelse(bh); | 769 | __brelse(bh); |
| @@ -794,6 +802,10 @@ wait_for_iobuf: | |||
| 794 | jbd2_journal_abort(journal, err); | 802 | jbd2_journal_abort(journal, err); |
| 795 | 803 | ||
| 796 | jbd_debug(3, "JBD: commit phase 5\n"); | 804 | jbd_debug(3, "JBD: commit phase 5\n"); |
| 805 | write_lock(&journal->j_state_lock); | ||
| 806 | J_ASSERT(commit_transaction->t_state == T_COMMIT_DFLUSH); | ||
| 807 | commit_transaction->t_state = T_COMMIT_JFLUSH; | ||
| 808 | write_unlock(&journal->j_state_lock); | ||
| 797 | 809 | ||
| 798 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 810 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, |
| 799 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | 811 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { |
| @@ -949,7 +961,7 @@ restart_loop: | |||
| 949 | 961 | ||
| 950 | jbd_debug(3, "JBD: commit phase 7\n"); | 962 | jbd_debug(3, "JBD: commit phase 7\n"); |
| 951 | 963 | ||
| 952 | J_ASSERT(commit_transaction->t_state == T_COMMIT); | 964 | J_ASSERT(commit_transaction->t_state == T_COMMIT_JFLUSH); |
| 953 | 965 | ||
| 954 | commit_transaction->t_start = jiffies; | 966 | commit_transaction->t_start = jiffies; |
| 955 | stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging, | 967 | stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging, |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e0ec3db1c395..9a7826990304 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -479,9 +479,12 @@ int __jbd2_log_space_left(journal_t *journal) | |||
| 479 | int __jbd2_log_start_commit(journal_t *journal, tid_t target) | 479 | int __jbd2_log_start_commit(journal_t *journal, tid_t target) |
| 480 | { | 480 | { |
| 481 | /* | 481 | /* |
| 482 | * Are we already doing a recent enough commit? | 482 | * The only transaction we can possibly wait upon is the |
| 483 | * currently running transaction (if it exists). Otherwise, | ||
| 484 | * the target tid must be an old one. | ||
| 483 | */ | 485 | */ |
| 484 | if (!tid_geq(journal->j_commit_request, target)) { | 486 | if (journal->j_running_transaction && |
| 487 | journal->j_running_transaction->t_tid == target) { | ||
| 485 | /* | 488 | /* |
| 486 | * We want a new commit: OK, mark the request and wakeup the | 489 | * We want a new commit: OK, mark the request and wakeup the |
| 487 | * commit thread. We do _not_ do the commit ourselves. | 490 | * commit thread. We do _not_ do the commit ourselves. |
| @@ -493,7 +496,15 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target) | |||
| 493 | journal->j_commit_sequence); | 496 | journal->j_commit_sequence); |
| 494 | wake_up(&journal->j_wait_commit); | 497 | wake_up(&journal->j_wait_commit); |
| 495 | return 1; | 498 | return 1; |
| 496 | } | 499 | } else if (!tid_geq(journal->j_commit_request, target)) |
| 500 | /* This should never happen, but if it does, preserve | ||
| 501 | the evidence before kjournald goes into a loop and | ||
| 502 | increments j_commit_sequence beyond all recognition. */ | ||
| 503 | WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n", | ||
| 504 | journal->j_commit_request, | ||
| 505 | journal->j_commit_sequence, | ||
| 506 | target, journal->j_running_transaction ? | ||
| 507 | journal->j_running_transaction->t_tid : 0); | ||
| 497 | return 0; | 508 | return 0; |
| 498 | } | 509 | } |
| 499 | 510 | ||
| @@ -577,6 +588,47 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) | |||
| 577 | } | 588 | } |
| 578 | 589 | ||
| 579 | /* | 590 | /* |
| 591 | * Return 1 if a given transaction has not yet sent barrier request | ||
| 592 | * connected with a transaction commit. If 0 is returned, transaction | ||
| 593 | * may or may not have sent the barrier. Used to avoid sending barrier | ||
| 594 | * twice in common cases. | ||
| 595 | */ | ||
| 596 | int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid) | ||
| 597 | { | ||
| 598 | int ret = 0; | ||
| 599 | transaction_t *commit_trans; | ||
| 600 | |||
| 601 | if (!(journal->j_flags & JBD2_BARRIER)) | ||
| 602 | return 0; | ||
| 603 | read_lock(&journal->j_state_lock); | ||
| 604 | /* Transaction already committed? */ | ||
| 605 | if (tid_geq(journal->j_commit_sequence, tid)) | ||
| 606 | goto out; | ||
| 607 | commit_trans = journal->j_committing_transaction; | ||
| 608 | if (!commit_trans || commit_trans->t_tid != tid) { | ||
| 609 | ret = 1; | ||
| 610 | goto out; | ||
| 611 | } | ||
| 612 | /* | ||
| 613 | * Transaction is being committed and we already proceeded to | ||
| 614 | * submitting a flush to fs partition? | ||
| 615 | */ | ||
| 616 | if (journal->j_fs_dev != journal->j_dev) { | ||
| 617 | if (!commit_trans->t_need_data_flush || | ||
| 618 | commit_trans->t_state >= T_COMMIT_DFLUSH) | ||
| 619 | goto out; | ||
| 620 | } else { | ||
| 621 | if (commit_trans->t_state >= T_COMMIT_JFLUSH) | ||
| 622 | goto out; | ||
| 623 | } | ||
| 624 | ret = 1; | ||
| 625 | out: | ||
| 626 | read_unlock(&journal->j_state_lock); | ||
| 627 | return ret; | ||
| 628 | } | ||
| 629 | EXPORT_SYMBOL(jbd2_trans_will_send_data_barrier); | ||
| 630 | |||
| 631 | /* | ||
| 580 | * Wait for a specified commit to complete. | 632 | * Wait for a specified commit to complete. |
| 581 | * The caller may not hold the journal lock. | 633 | * The caller may not hold the journal lock. |
| 582 | */ | 634 | */ |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 05fa77a23711..3eec82d32fd4 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -82,7 +82,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
| 82 | */ | 82 | */ |
| 83 | 83 | ||
| 84 | /* | 84 | /* |
| 85 | * Update transiaction's maximum wait time, if debugging is enabled. | 85 | * Update transaction's maximum wait time, if debugging is enabled. |
| 86 | * | 86 | * |
| 87 | * In order for t_max_wait to be reliable, it must be protected by a | 87 | * In order for t_max_wait to be reliable, it must be protected by a |
| 88 | * lock. But doing so will mean that start_this_handle() can not be | 88 | * lock. But doing so will mean that start_this_handle() can not be |
| @@ -91,11 +91,10 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
| 91 | * means that maximum wait time reported by the jbd2_run_stats | 91 | * means that maximum wait time reported by the jbd2_run_stats |
| 92 | * tracepoint will always be zero. | 92 | * tracepoint will always be zero. |
| 93 | */ | 93 | */ |
| 94 | static inline void update_t_max_wait(transaction_t *transaction) | 94 | static inline void update_t_max_wait(transaction_t *transaction, |
| 95 | unsigned long ts) | ||
| 95 | { | 96 | { |
| 96 | #ifdef CONFIG_JBD2_DEBUG | 97 | #ifdef CONFIG_JBD2_DEBUG |
| 97 | unsigned long ts = jiffies; | ||
| 98 | |||
| 99 | if (jbd2_journal_enable_debug && | 98 | if (jbd2_journal_enable_debug && |
| 100 | time_after(transaction->t_start, ts)) { | 99 | time_after(transaction->t_start, ts)) { |
| 101 | ts = jbd2_time_diff(ts, transaction->t_start); | 100 | ts = jbd2_time_diff(ts, transaction->t_start); |
| @@ -121,6 +120,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle, | |||
| 121 | tid_t tid; | 120 | tid_t tid; |
| 122 | int needed, need_to_start; | 121 | int needed, need_to_start; |
| 123 | int nblocks = handle->h_buffer_credits; | 122 | int nblocks = handle->h_buffer_credits; |
| 123 | unsigned long ts = jiffies; | ||
| 124 | 124 | ||
| 125 | if (nblocks > journal->j_max_transaction_buffers) { | 125 | if (nblocks > journal->j_max_transaction_buffers) { |
| 126 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", | 126 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", |
| @@ -271,7 +271,7 @@ repeat: | |||
| 271 | /* OK, account for the buffers that this operation expects to | 271 | /* OK, account for the buffers that this operation expects to |
| 272 | * use and add the handle to the running transaction. | 272 | * use and add the handle to the running transaction. |
| 273 | */ | 273 | */ |
| 274 | update_t_max_wait(transaction); | 274 | update_t_max_wait(transaction, ts); |
| 275 | handle->h_transaction = transaction; | 275 | handle->h_transaction = transaction; |
| 276 | atomic_inc(&transaction->t_updates); | 276 | atomic_inc(&transaction->t_updates); |
| 277 | atomic_inc(&transaction->t_handle_count); | 277 | atomic_inc(&transaction->t_handle_count); |
| @@ -316,7 +316,8 @@ static handle_t *new_handle(int nblocks) | |||
| 316 | * This function is visible to journal users (like ext3fs), so is not | 316 | * This function is visible to journal users (like ext3fs), so is not |
| 317 | * called with the journal already locked. | 317 | * called with the journal already locked. |
| 318 | * | 318 | * |
| 319 | * Return a pointer to a newly allocated handle, or NULL on failure | 319 | * Return a pointer to a newly allocated handle, or an ERR_PTR() value |
| 320 | * on failure. | ||
| 320 | */ | 321 | */ |
| 321 | handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask) | 322 | handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask) |
| 322 | { | 323 | { |
| @@ -921,8 +922,8 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) | |||
| 921 | */ | 922 | */ |
| 922 | JBUFFER_TRACE(jh, "cancelling revoke"); | 923 | JBUFFER_TRACE(jh, "cancelling revoke"); |
| 923 | jbd2_journal_cancel_revoke(handle, jh); | 924 | jbd2_journal_cancel_revoke(handle, jh); |
| 924 | jbd2_journal_put_journal_head(jh); | ||
| 925 | out: | 925 | out: |
| 926 | jbd2_journal_put_journal_head(jh); | ||
| 926 | return err; | 927 | return err; |
| 927 | } | 928 | } |
| 928 | 929 | ||
| @@ -2147,6 +2148,13 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) | |||
| 2147 | jinode->i_next_transaction == transaction) | 2148 | jinode->i_next_transaction == transaction) |
| 2148 | goto done; | 2149 | goto done; |
| 2149 | 2150 | ||
| 2151 | /* | ||
| 2152 | * We only ever set this variable to 1 so the test is safe. Since | ||
| 2153 | * t_need_data_flush is likely to be set, we do the test to save some | ||
| 2154 | * cacheline bouncing | ||
| 2155 | */ | ||
| 2156 | if (!transaction->t_need_data_flush) | ||
| 2157 | transaction->t_need_data_flush = 1; | ||
| 2150 | /* On some different transaction's list - should be | 2158 | /* On some different transaction's list - should be |
| 2151 | * the committing one */ | 2159 | * the committing one */ |
| 2152 | if (jinode->i_transaction) { | 2160 | if (jinode->i_transaction) { |
