| 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 |
| |
| |
| @@ -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); |
| } |
| |