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