summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_aops.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-08-23 08:28:10 +0000
committerAlex Elder <aelder@sgi.com>2011-10-11 21:15:00 -0500
commitc859cdd1da008b3825555be3242908088a3de366 (patch)
tree0d5c5d22d1d10a346da81990a3c94bfabfd03904 /fs/xfs/xfs_aops.c
parent398d25ef23b10ce75424e0336a8d059dda1dbc8d (diff)
xfs: defer AIO/DIO completions
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@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_aops.c')
-rw-r--r--fs/xfs/xfs_aops.c26
1 files changed, 9 insertions, 17 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index d91564404abf..10660c364105 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -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;
@@ -1289,7 +1293,6 @@ xfs_end_io_direct_write(
bool is_async)
{
struct xfs_ioend *ioend = iocb->private;
- struct inode *inode = ioend->io_inode;
/*
* blockdev_direct_IO can return an error even after the I/O
@@ -1300,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(inode);
}
STATIC ssize_t