mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
40e2e97316
commit
fb511f2150
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue