Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e927af90aaa7d75543edbbd9c2810e6963d0443f
Commit:     e927af90aaa7d75543edbbd9c2810e6963d0443f
Parent:     f4a9f28a909debe97cd3f6ca30e82e5811125bff
Author:     David Chinner <[EMAIL PROTECTED]>
AuthorDate: Tue Jun 5 16:24:36 2007 +1000
Committer:  Tim Shimmin <[EMAIL PROTECTED]>
CommitDate: Sat Jul 14 15:30:52 2007 +1000

    [XFS] Block on unwritten extent conversion during synchronous direct I/O.
    
    Currently we do not wait on extent conversion to occur, and hence we can
    return to userspace from a synchronous direct I/O write without having
    completed all the actions in the write. Hence a read after the write may
    see zeroes (unwritten extent) rather than the data that was written.
    
    Block the I/O completion by triggering a synchronous workqueue flush to
    ensure that the conversion has occurred before we return to userspace.
    
    SGI-PV: 964092
    SGI-Modid: xfs-linux-melb:xfs-kern:28775a
    
    Signed-off-by: David Chinner <[EMAIL PROTECTED]>
    Signed-off-by: Tim Shimmin <[EMAIL PROTECTED]>
---
 fs/xfs/linux-2.6/xfs_aops.c |   28 ++++++++++++++++++++--------
 1 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 7361861..80a3214 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -108,14 +108,19 @@ xfs_page_trace(
 
 /*
  * Schedule IO completion handling on a xfsdatad if this was
- * the final hold on this ioend.
+ * the final hold on this ioend. If we are asked to wait,
+ * flush the workqueue.
  */
 STATIC void
 xfs_finish_ioend(
-       xfs_ioend_t             *ioend)
+       xfs_ioend_t     *ioend,
+       int             wait)
 {
-       if (atomic_dec_and_test(&ioend->io_remaining))
+       if (atomic_dec_and_test(&ioend->io_remaining)) {
                queue_work(xfsdatad_workqueue, &ioend->io_work);
+               if (wait)
+                       flush_workqueue(xfsdatad_workqueue);
+       }
 }
 
 /*
@@ -334,7 +339,7 @@ xfs_end_bio(
        bio->bi_end_io = NULL;
        bio_put(bio);
 
-       xfs_finish_ioend(ioend);
+       xfs_finish_ioend(ioend, 0);
        return 0;
 }
 
@@ -470,7 +475,7 @@ xfs_submit_ioend(
                }
                if (bio)
                        xfs_submit_ioend_bio(ioend, bio);
-               xfs_finish_ioend(ioend);
+               xfs_finish_ioend(ioend, 0);
        } while ((ioend = next) != NULL);
 }
 
@@ -1416,6 +1421,13 @@ xfs_end_io_direct(
         * This is not necessary for synchronous direct I/O, but we do
         * it anyway to keep the code uniform and simpler.
         *
+        * Well, if only it were that simple. Because synchronous direct I/O
+        * requires extent conversion to occur *before* we return to userspace,
+        * we have to wait for extent conversion to complete. Look at the
+        * iocb that has been passed to us to determine if this is AIO or
+        * not. If it is synchronous, tell xfs_finish_ioend() to kick the
+        * workqueue and wait for it to complete.
+        *
         * The core direct I/O code might be changed to always call the
         * completion handler in the future, in which case all this can
         * go away.
@@ -1423,9 +1435,9 @@ xfs_end_io_direct(
        ioend->io_offset = offset;
        ioend->io_size = size;
        if (ioend->io_type == IOMAP_READ) {
-               xfs_finish_ioend(ioend);
+               xfs_finish_ioend(ioend, 0);
        } else if (private && size > 0) {
-               xfs_finish_ioend(ioend);
+               xfs_finish_ioend(ioend, is_sync_kiocb(iocb));
        } else {
                /*
                 * A direct I/O write ioend starts it's life in unwritten
@@ -1434,7 +1446,7 @@ xfs_end_io_direct(
                 * handler.
                 */
                INIT_WORK(&ioend->io_work, xfs_end_bio_written);
-               xfs_finish_ioend(ioend);
+               xfs_finish_ioend(ioend, 0);
        }
 
        /*
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to