xfs
[Top] [All Lists]

[PATCH 2/5] xfs: defer AIO/DIO completions

To: xfs@xxxxxxxxxxx
Subject: [PATCH 2/5] xfs: defer AIO/DIO completions
From: Christoph Hellwig <hch@xxxxxxxxxxxxx>
Date: Sun, 14 Aug 2011 18:24:14 -0400
References: <20110814222412.359079843@xxxxxxxxxxxxxxxxxxxxxx>
User-agent: quilt/0.48-1
We really shouldn't complete AIO or DIO requests until we have finished
the unwritten extent conversion and size update.  This means fsync never
has to pick up any ioends as all work has been completed when signalling
I/O completion.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>

Index: xfs/fs/xfs/xfs_aops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_aops.c  2011-08-13 06:54:41.188441655 -0700
+++ xfs/fs/xfs/xfs_aops.c       2011-08-13 10:56:13.109932177 -0700
@@ -122,6 +122,11 @@ xfs_destroy_ioend(
                bh->b_end_io(bh, !ioend->io_error);
        }
 
+       if (ioend->io_iocb) {
+               if (ioend->io_buffer_tail == (struct buffer_head *)1)
+                       aio_complete(ioend->io_iocb, ioend->io_result, 0);
+               inode_dio_done(ioend->io_inode);
+       }
        xfs_ioend_wake(ip);
        mempool_free(ioend, xfs_ioend_pool);
 }
@@ -236,8 +241,6 @@ xfs_end_io(
                /* ensure we don't spin on blocked ioends */
                delay(1);
        } else {
-               if (ioend->io_iocb)
-                       aio_complete(ioend->io_iocb, ioend->io_result, 0);
                xfs_destroy_ioend(ioend);
        }
 }
@@ -1299,28 +1302,24 @@ xfs_end_io_direct_write(
 
        ioend->io_offset = offset;
        ioend->io_size = size;
+       ioend->io_iocb = iocb;
+       ioend->io_result = ret;
        if (private && size > 0)
                ioend->io_type = IO_UNWRITTEN;
 
        if (is_async) {
                /*
-                * If we are converting an unwritten extent we need to delay
-                * the AIO completion until after the unwrittent extent
-                * conversion has completed, otherwise do it ASAP.
+                * Abuse a field not use for direct I/O as an indicator that
+                * we have to call aio_complete.  Unfortunatly an
+                * is_sync_kiocb check is not enough for that as some
+                * various aio-submitted iocbs may be treated as synchronous
+                * I/O in the end.
                 */
-               if (ioend->io_type == IO_UNWRITTEN) {
-                       ioend->io_iocb = iocb;
-                       ioend->io_result = ret;
-               } else {
-                       aio_complete(iocb, ret, 0);
-               }
+               ioend->io_buffer_tail = (struct buffer_head *)1;
                xfs_finish_ioend(ioend);
        } else {
                xfs_finish_ioend_sync(ioend);
        }
-
-       /* XXX: probably should move into the real I/O completion handler */
-       inode_dio_done(ioend->io_inode);
 }
 
 STATIC ssize_t

<Prev in Thread] Current Thread [Next in Thread>