diff options
Diffstat (limited to 'fs/jbd2/commit.c')
| -rw-r--r-- | fs/jbd2/commit.c | 97 |
1 files changed, 50 insertions, 47 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 26d991ddc1e6..671da7fb7ffd 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -259,6 +259,7 @@ static int journal_submit_data_buffers(journal_t *journal, | |||
| 259 | ret = err; | 259 | ret = err; |
| 260 | spin_lock(&journal->j_list_lock); | 260 | spin_lock(&journal->j_list_lock); |
| 261 | J_ASSERT(jinode->i_transaction == commit_transaction); | 261 | J_ASSERT(jinode->i_transaction == commit_transaction); |
| 262 | commit_transaction->t_flushed_data_blocks = 1; | ||
| 262 | jinode->i_flags &= ~JI_COMMIT_RUNNING; | 263 | jinode->i_flags &= ~JI_COMMIT_RUNNING; |
| 263 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); | 264 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); |
| 264 | } | 265 | } |
| @@ -286,7 +287,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal, | |||
| 286 | if (err) { | 287 | if (err) { |
| 287 | /* | 288 | /* |
| 288 | * Because AS_EIO is cleared by | 289 | * Because AS_EIO is cleared by |
| 289 | * wait_on_page_writeback_range(), set it again so | 290 | * filemap_fdatawait_range(), set it again so |
| 290 | * that user process can get -EIO from fsync(). | 291 | * that user process can get -EIO from fsync(). |
| 291 | */ | 292 | */ |
| 292 | set_bit(AS_EIO, | 293 | set_bit(AS_EIO, |
| @@ -410,10 +411,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 410 | if (commit_transaction->t_synchronous_commit) | 411 | if (commit_transaction->t_synchronous_commit) |
| 411 | write_op = WRITE_SYNC_PLUG; | 412 | write_op = WRITE_SYNC_PLUG; |
| 412 | trace_jbd2_commit_locking(journal, commit_transaction); | 413 | trace_jbd2_commit_locking(journal, commit_transaction); |
| 413 | stats.u.run.rs_wait = commit_transaction->t_max_wait; | 414 | stats.run.rs_wait = commit_transaction->t_max_wait; |
| 414 | stats.u.run.rs_locked = jiffies; | 415 | stats.run.rs_locked = jiffies; |
| 415 | stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start, | 416 | stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start, |
| 416 | stats.u.run.rs_locked); | 417 | stats.run.rs_locked); |
| 417 | 418 | ||
| 418 | spin_lock(&commit_transaction->t_handle_lock); | 419 | spin_lock(&commit_transaction->t_handle_lock); |
| 419 | while (commit_transaction->t_updates) { | 420 | while (commit_transaction->t_updates) { |
| @@ -486,9 +487,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 486 | jbd2_journal_switch_revoke_table(journal); | 487 | jbd2_journal_switch_revoke_table(journal); |
| 487 | 488 | ||
| 488 | trace_jbd2_commit_flushing(journal, commit_transaction); | 489 | trace_jbd2_commit_flushing(journal, commit_transaction); |
| 489 | stats.u.run.rs_flushing = jiffies; | 490 | stats.run.rs_flushing = jiffies; |
| 490 | stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked, | 491 | stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked, |
| 491 | stats.u.run.rs_flushing); | 492 | stats.run.rs_flushing); |
| 492 | 493 | ||
| 493 | commit_transaction->t_state = T_FLUSH; | 494 | commit_transaction->t_state = T_FLUSH; |
| 494 | journal->j_committing_transaction = commit_transaction; | 495 | journal->j_committing_transaction = commit_transaction; |
| @@ -523,11 +524,11 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 523 | spin_unlock(&journal->j_state_lock); | 524 | spin_unlock(&journal->j_state_lock); |
| 524 | 525 | ||
| 525 | trace_jbd2_commit_logging(journal, commit_transaction); | 526 | trace_jbd2_commit_logging(journal, commit_transaction); |
| 526 | stats.u.run.rs_logging = jiffies; | 527 | stats.run.rs_logging = jiffies; |
| 527 | stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing, | 528 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, |
| 528 | stats.u.run.rs_logging); | 529 | stats.run.rs_logging); |
| 529 | stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits; | 530 | stats.run.rs_blocks = commit_transaction->t_outstanding_credits; |
| 530 | stats.u.run.rs_blocks_logged = 0; | 531 | stats.run.rs_blocks_logged = 0; |
| 531 | 532 | ||
| 532 | J_ASSERT(commit_transaction->t_nr_buffers <= | 533 | J_ASSERT(commit_transaction->t_nr_buffers <= |
| 533 | commit_transaction->t_outstanding_credits); | 534 | commit_transaction->t_outstanding_credits); |
| @@ -636,6 +637,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 636 | JBUFFER_TRACE(jh, "ph3: write metadata"); | 637 | JBUFFER_TRACE(jh, "ph3: write metadata"); |
| 637 | flags = jbd2_journal_write_metadata_buffer(commit_transaction, | 638 | flags = jbd2_journal_write_metadata_buffer(commit_transaction, |
| 638 | jh, &new_jh, blocknr); | 639 | jh, &new_jh, blocknr); |
| 640 | if (flags < 0) { | ||
| 641 | jbd2_journal_abort(journal, flags); | ||
| 642 | continue; | ||
| 643 | } | ||
| 639 | set_bit(BH_JWrite, &jh2bh(new_jh)->b_state); | 644 | set_bit(BH_JWrite, &jh2bh(new_jh)->b_state); |
| 640 | wbuf[bufs++] = jh2bh(new_jh); | 645 | wbuf[bufs++] = jh2bh(new_jh); |
| 641 | 646 | ||
| @@ -695,7 +700,7 @@ start_journal_io: | |||
| 695 | submit_bh(write_op, bh); | 700 | submit_bh(write_op, bh); |
| 696 | } | 701 | } |
| 697 | cond_resched(); | 702 | cond_resched(); |
| 698 | stats.u.run.rs_blocks_logged += bufs; | 703 | stats.run.rs_blocks_logged += bufs; |
| 699 | 704 | ||
| 700 | /* Force a new descriptor to be generated next | 705 | /* Force a new descriptor to be generated next |
| 701 | time round the loop. */ | 706 | time round the loop. */ |
| @@ -704,8 +709,17 @@ start_journal_io: | |||
| 704 | } | 709 | } |
| 705 | } | 710 | } |
| 706 | 711 | ||
| 707 | /* Done it all: now write the commit record asynchronously. */ | 712 | /* |
| 713 | * If the journal is not located on the file system device, | ||
| 714 | * then we must flush the file system device before we issue | ||
| 715 | * the commit record | ||
| 716 | */ | ||
| 717 | if (commit_transaction->t_flushed_data_blocks && | ||
| 718 | (journal->j_fs_dev != journal->j_dev) && | ||
| 719 | (journal->j_flags & JBD2_BARRIER)) | ||
| 720 | blkdev_issue_flush(journal->j_fs_dev, NULL); | ||
| 708 | 721 | ||
| 722 | /* Done it all: now write the commit record asynchronously. */ | ||
| 709 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 723 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, |
| 710 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | 724 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { |
| 711 | err = journal_submit_commit_record(journal, commit_transaction, | 725 | err = journal_submit_commit_record(journal, commit_transaction, |
| @@ -716,13 +730,6 @@ start_journal_io: | |||
| 716 | blkdev_issue_flush(journal->j_dev, NULL); | 730 | blkdev_issue_flush(journal->j_dev, NULL); |
| 717 | } | 731 | } |
| 718 | 732 | ||
| 719 | /* | ||
| 720 | * This is the right place to wait for data buffers both for ASYNC | ||
| 721 | * and !ASYNC commit. If commit is ASYNC, we need to wait only after | ||
| 722 | * the commit block went to disk (which happens above). If commit is | ||
| 723 | * SYNC, we need to wait for data buffers before we start writing | ||
| 724 | * commit block, which happens below in such setting. | ||
| 725 | */ | ||
| 726 | err = journal_finish_inode_data_buffers(journal, commit_transaction); | 733 | err = journal_finish_inode_data_buffers(journal, commit_transaction); |
| 727 | if (err) { | 734 | if (err) { |
| 728 | printk(KERN_WARNING | 735 | printk(KERN_WARNING |
| @@ -876,8 +883,7 @@ restart_loop: | |||
| 876 | spin_unlock(&journal->j_list_lock); | 883 | spin_unlock(&journal->j_list_lock); |
| 877 | bh = jh2bh(jh); | 884 | bh = jh2bh(jh); |
| 878 | jbd_lock_bh_state(bh); | 885 | jbd_lock_bh_state(bh); |
| 879 | J_ASSERT_JH(jh, jh->b_transaction == commit_transaction || | 886 | J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); |
| 880 | jh->b_transaction == journal->j_running_transaction); | ||
| 881 | 887 | ||
| 882 | /* | 888 | /* |
| 883 | * If there is undo-protected committed data against | 889 | * If there is undo-protected committed data against |
| @@ -923,12 +929,12 @@ restart_loop: | |||
| 923 | /* A buffer which has been freed while still being | 929 | /* A buffer which has been freed while still being |
| 924 | * journaled by a previous transaction may end up still | 930 | * journaled by a previous transaction may end up still |
| 925 | * being dirty here, but we want to avoid writing back | 931 | * being dirty here, but we want to avoid writing back |
| 926 | * that buffer in the future now that the last use has | 932 | * that buffer in the future after the "add to orphan" |
| 927 | * been committed. That's not only a performance gain, | 933 | * operation been committed, That's not only a performance |
| 928 | * it also stops aliasing problems if the buffer is left | 934 | * gain, it also stops aliasing problems if the buffer is |
| 929 | * behind for writeback and gets reallocated for another | 935 | * left behind for writeback and gets reallocated for another |
| 930 | * use in a different page. */ | 936 | * use in a different page. */ |
| 931 | if (buffer_freed(bh)) { | 937 | if (buffer_freed(bh) && !jh->b_next_transaction) { |
| 932 | clear_buffer_freed(bh); | 938 | clear_buffer_freed(bh); |
| 933 | clear_buffer_jbddirty(bh); | 939 | clear_buffer_jbddirty(bh); |
| 934 | } | 940 | } |
| @@ -988,33 +994,30 @@ restart_loop: | |||
| 988 | J_ASSERT(commit_transaction->t_state == T_COMMIT); | 994 | J_ASSERT(commit_transaction->t_state == T_COMMIT); |
| 989 | 995 | ||
| 990 | commit_transaction->t_start = jiffies; | 996 | commit_transaction->t_start = jiffies; |
| 991 | stats.u.run.rs_logging = jbd2_time_diff(stats.u.run.rs_logging, | 997 | stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging, |
| 992 | commit_transaction->t_start); | 998 | commit_transaction->t_start); |
| 993 | 999 | ||
| 994 | /* | 1000 | /* |
| 995 | * File the transaction for history | 1001 | * File the transaction statistics |
| 996 | */ | 1002 | */ |
| 997 | stats.ts_type = JBD2_STATS_RUN; | ||
| 998 | stats.ts_tid = commit_transaction->t_tid; | 1003 | stats.ts_tid = commit_transaction->t_tid; |
| 999 | stats.u.run.rs_handle_count = commit_transaction->t_handle_count; | 1004 | stats.run.rs_handle_count = commit_transaction->t_handle_count; |
| 1000 | spin_lock(&journal->j_history_lock); | 1005 | trace_jbd2_run_stats(journal->j_fs_dev->bd_dev, |
| 1001 | memcpy(journal->j_history + journal->j_history_cur, &stats, | 1006 | commit_transaction->t_tid, &stats.run); |
| 1002 | sizeof(stats)); | ||
| 1003 | if (++journal->j_history_cur == journal->j_history_max) | ||
| 1004 | journal->j_history_cur = 0; | ||
| 1005 | 1007 | ||
| 1006 | /* | 1008 | /* |
| 1007 | * Calculate overall stats | 1009 | * Calculate overall stats |
| 1008 | */ | 1010 | */ |
| 1011 | spin_lock(&journal->j_history_lock); | ||
| 1009 | journal->j_stats.ts_tid++; | 1012 | journal->j_stats.ts_tid++; |
| 1010 | journal->j_stats.u.run.rs_wait += stats.u.run.rs_wait; | 1013 | journal->j_stats.run.rs_wait += stats.run.rs_wait; |
| 1011 | journal->j_stats.u.run.rs_running += stats.u.run.rs_running; | 1014 | journal->j_stats.run.rs_running += stats.run.rs_running; |
| 1012 | journal->j_stats.u.run.rs_locked += stats.u.run.rs_locked; | 1015 | journal->j_stats.run.rs_locked += stats.run.rs_locked; |
| 1013 | journal->j_stats.u.run.rs_flushing += stats.u.run.rs_flushing; | 1016 | journal->j_stats.run.rs_flushing += stats.run.rs_flushing; |
| 1014 | journal->j_stats.u.run.rs_logging += stats.u.run.rs_logging; | 1017 | journal->j_stats.run.rs_logging += stats.run.rs_logging; |
| 1015 | journal->j_stats.u.run.rs_handle_count += stats.u.run.rs_handle_count; | 1018 | journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count; |
| 1016 | journal->j_stats.u.run.rs_blocks += stats.u.run.rs_blocks; | 1019 | journal->j_stats.run.rs_blocks += stats.run.rs_blocks; |
| 1017 | journal->j_stats.u.run.rs_blocks_logged += stats.u.run.rs_blocks_logged; | 1020 | journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; |
| 1018 | spin_unlock(&journal->j_history_lock); | 1021 | spin_unlock(&journal->j_history_lock); |
| 1019 | 1022 | ||
| 1020 | commit_transaction->t_state = T_FINISHED; | 1023 | commit_transaction->t_state = T_FINISHED; |
