84 lines
2.6 KiB
Diff
84 lines
2.6 KiB
Diff
|
From: Christoph Hellwig <hch@infradead.org>
|
||
|
Date: Sun, 18 Jul 2010 21:17:10 +0000 (+0000)
|
||
|
Subject: xfs: move aio completion after unwritten extent conversion
|
||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=fb511f2150174b18b28ad54708c1adda0df39b17
|
||
|
|
||
|
xfs: move aio completion after unwritten extent conversion
|
||
|
|
||
|
If we write into an unwritten extent using AIO we need to complete the AIO
|
||
|
request after the extent conversion has finished. Without that a read could
|
||
|
race to see see the extent still unwritten and return zeros. For synchronous
|
||
|
I/O we already take care of that by flushing the xfsconvertd workqueue (which
|
||
|
might be a bit of overkill).
|
||
|
|
||
|
To do that add iocb and result fields to struct xfs_ioend, so that we can
|
||
|
call aio_complete from xfs_end_io after the extent conversion has happened.
|
||
|
Note that we need a new result field as io_error is used for positive errno
|
||
|
values, while the AIO code can return negative error values and positive
|
||
|
transfer sizes.
|
||
|
|
||
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||
|
Reviewed-by: Dave Chinner <dchinner@redhat.com>
|
||
|
Signed-off-by: Alex Elder <aelder@sgi.com>
|
||
|
---
|
||
|
|
||
|
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
|
||
|
index 95d1e26..13622d5 100644
|
||
|
--- a/fs/xfs/linux-2.6/xfs_aops.c
|
||
|
+++ b/fs/xfs/linux-2.6/xfs_aops.c
|
||
|
@@ -265,8 +265,11 @@ xfs_end_io(
|
||
|
xfs_finish_ioend(ioend, 0);
|
||
|
/* ensure we don't spin on blocked ioends */
|
||
|
delay(1);
|
||
|
- } else
|
||
|
+ } else {
|
||
|
+ if (ioend->io_iocb)
|
||
|
+ aio_complete(ioend->io_iocb, ioend->io_result, 0);
|
||
|
xfs_destroy_ioend(ioend);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
@@ -299,6 +302,8 @@ xfs_alloc_ioend(
|
||
|
atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
|
||
|
ioend->io_offset = 0;
|
||
|
ioend->io_size = 0;
|
||
|
+ ioend->io_iocb = NULL;
|
||
|
+ ioend->io_result = 0;
|
||
|
|
||
|
INIT_WORK(&ioend->io_work, xfs_end_io);
|
||
|
return ioend;
|
||
|
@@ -1411,6 +1416,7 @@ xfs_end_io_direct(
|
||
|
bool is_async)
|
||
|
{
|
||
|
xfs_ioend_t *ioend = iocb->private;
|
||
|
+ bool complete_aio = is_async;
|
||
|
|
||
|
/*
|
||
|
* Non-NULL private data means we need to issue a transaction to
|
||
|
@@ -1436,7 +1442,14 @@ xfs_end_io_direct(
|
||
|
if (ioend->io_type == IO_READ) {
|
||
|
xfs_finish_ioend(ioend, 0);
|
||
|
} else if (private && size > 0) {
|
||
|
- xfs_finish_ioend(ioend, is_sync_kiocb(iocb));
|
||
|
+ if (is_async) {
|
||
|
+ ioend->io_iocb = iocb;
|
||
|
+ ioend->io_result = ret;
|
||
|
+ complete_aio = false;
|
||
|
+ xfs_finish_ioend(ioend, 0);
|
||
|
+ } else {
|
||
|
+ xfs_finish_ioend(ioend, 1);
|
||
|
+ }
|
||
|
} else {
|
||
|
/*
|
||
|
* A direct I/O write ioend starts it's life in unwritten
|
||
|
@@ -1455,7 +1468,7 @@ xfs_end_io_direct(
|
||
|
*/
|
||
|
iocb->private = NULL;
|
||
|
|
||
|
- if (is_async)
|
||
|
+ if (complete_aio)
|
||
|
aio_complete(iocb, ret, 0);
|
||
|
}
|
||
|
|