mmc: s3c6410: enable ADMA feature in 6410 sdhci controller
[safe/jmp/linux-2.6] / fs / jbd2 / commit.c
index 8896c1d..75716d3 100644 (file)
@@ -259,6 +259,7 @@ static int journal_submit_data_buffers(journal_t *journal,
                        ret = err;
                spin_lock(&journal->j_list_lock);
                J_ASSERT(jinode->i_transaction == commit_transaction);
+               commit_transaction->t_flushed_data_blocks = 1;
                jinode->i_flags &= ~JI_COMMIT_RUNNING;
                wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
        }
@@ -286,7 +287,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
                if (err) {
                        /*
                         * Because AS_EIO is cleared by
-                        * wait_on_page_writeback_range(), set it again so
+                        * filemap_fdatawait_range(), set it again so
                         * that user process can get -EIO from fsync().
                         */
                        set_bit(AS_EIO,
@@ -708,8 +709,18 @@ start_journal_io:
                }
        }
 
-       /* Done it all: now write the commit record asynchronously. */
+       /* 
+        * If the journal is not located on the file system device,
+        * then we must flush the file system device before we issue
+        * the commit record
+        */
+       if (commit_transaction->t_flushed_data_blocks &&
+           (journal->j_fs_dev != journal->j_dev) &&
+           (journal->j_flags & JBD2_BARRIER))
+               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL,
+                       BLKDEV_IFL_WAIT);
 
+       /* Done it all: now write the commit record asynchronously. */
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
                                      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
                err = journal_submit_commit_record(journal, commit_transaction,
@@ -717,16 +728,10 @@ start_journal_io:
                if (err)
                        __jbd2_journal_abort_hard(journal);
                if (journal->j_flags & JBD2_BARRIER)
-                       blkdev_issue_flush(journal->j_dev, NULL);
+                       blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL,
+                               BLKDEV_IFL_WAIT);
        }
 
-       /*
-        * This is the right place to wait for data buffers both for ASYNC
-        * and !ASYNC commit. If commit is ASYNC, we need to wait only after
-        * the commit block went to disk (which happens above). If commit is
-        * SYNC, we need to wait for data buffers before we start writing
-        * commit block, which happens below in such setting.
-        */
        err = journal_finish_inode_data_buffers(journal, commit_transaction);
        if (err) {
                printk(KERN_WARNING
@@ -880,8 +885,7 @@ restart_loop:
                spin_unlock(&journal->j_list_lock);
                bh = jh2bh(jh);
                jbd_lock_bh_state(bh);
-               J_ASSERT_JH(jh, jh->b_transaction == commit_transaction ||
-                       jh->b_transaction == journal->j_running_transaction);
+               J_ASSERT_JH(jh, jh->b_transaction == commit_transaction);
 
                /*
                 * If there is undo-protected committed data against
@@ -927,12 +931,12 @@ restart_loop:
                /* A buffer which has been freed while still being
                 * journaled by a previous transaction may end up still
                 * being dirty here, but we want to avoid writing back
-                * that buffer in the future now that the last use has
-                * been committed.  That's not only a performance gain,
-                * it also stops aliasing problems if the buffer is left
-                * behind for writeback and gets reallocated for another
+                * that buffer in the future after the "add to orphan"
+                * operation been committed,  That's not only a performance
+                * gain, it also stops aliasing problems if the buffer is
+                * left behind for writeback and gets reallocated for another
                 * use in a different page. */
-               if (buffer_freed(bh)) {
+               if (buffer_freed(bh) && !jh->b_next_transaction) {
                        clear_buffer_freed(bh);
                        clear_buffer_jbddirty(bh);
                }