diff options
Diffstat (limited to 'fs/jbd2/commit.c')
| -rw-r--r-- | fs/jbd2/commit.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index d4cfd6d2779e..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, |
| @@ -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 | ||
| @@ -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 | } |
