xfs
[Top] [All Lists]

[PATCH 08/11] xfs: defer AIO/DIO completions

To: xfs@xxxxxxxxxxx
Subject: [PATCH 08/11] xfs: defer AIO/DIO completions
From: Christoph Hellwig <hch@xxxxxxxxxxxxx>
Date: Tue, 23 Aug 2011 04:28:10 -0400
References: <20110823082802.335389799@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-23 04:39:29.027667347 +0200
+++ xfs/fs/xfs/xfs_aops.c       2011-08-23 04:39:56.914196267 +0200
@@ -122,6 +122,11 @@ xfs_destroy_ioend(
                bh->b_end_io(bh, !ioend->io_error);
        }
 
+       if (ioend->io_iocb) {
+               if (ioend->io_isasync)
+                       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);
        }
 }
@@ -274,6 +277,7 @@ xfs_alloc_ioend(
         * all the I/O from calling the completion routine too early.
         */
        atomic_set(&ioend->io_remaining, 1);
+       ioend->io_isasync = 0;
        ioend->io_error = 0;
        ioend->io_list = NULL;
        ioend->io_type = type;
@@ -1299,28 +1303,17 @@ 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.
-                */
-               if (ioend->io_type == IO_UNWRITTEN) {
-                       ioend->io_iocb = iocb;
-                       ioend->io_result = ret;
-               } else {
-                       aio_complete(iocb, ret, 0);
-               }
+               ioend->io_isasync = 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
Index: xfs/fs/xfs/xfs_aops.h
===================================================================
--- xfs.orig/fs/xfs/xfs_aops.h  2011-08-23 04:39:24.057694271 +0200
+++ xfs/fs/xfs/xfs_aops.h       2011-08-23 04:39:29.900995938 +0200
@@ -47,6 +47,7 @@ typedef struct xfs_ioend {
        unsigned int            io_type;        /* delalloc / unwritten */
        int                     io_error;       /* I/O error code */
        atomic_t                io_remaining;   /* hold count */
+       unsigned int            io_isasync : 1; /* needs aio_complete */
        struct inode            *io_inode;      /* file being written to */
        struct buffer_head      *io_buffer_head;/* buffer linked list head */
        struct buffer_head      *io_buffer_tail;/* buffer linked list tail */

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