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>
This commit is contained in:
Christoph Hellwig 2011-08-23 08:28:10 +00:00 committed by Alex Elder
parent 398d25ef23
commit c859cdd1da
2 changed files with 10 additions and 17 deletions

View File

@ -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

View File

@ -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 */