Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c859cdd1 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Alex Elder
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent 398d25ef
Loading
Loading
Loading
Loading
+9 −17
Original line number Original line Diff line number Diff line
@@ -122,6 +122,11 @@ xfs_destroy_ioend(
		bh->b_end_io(bh, !ioend->io_error);
		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);
	xfs_ioend_wake(ip);
	mempool_free(ioend, xfs_ioend_pool);
	mempool_free(ioend, xfs_ioend_pool);
}
}
@@ -236,8 +241,6 @@ xfs_end_io(
		/* ensure we don't spin on blocked ioends */
		/* ensure we don't spin on blocked ioends */
		delay(1);
		delay(1);
	} else {
	} else {
		if (ioend->io_iocb)
			aio_complete(ioend->io_iocb, ioend->io_result, 0);
		xfs_destroy_ioend(ioend);
		xfs_destroy_ioend(ioend);
	}
	}
}
}
@@ -274,6 +277,7 @@ xfs_alloc_ioend(
	 * all the I/O from calling the completion routine too early.
	 * all the I/O from calling the completion routine too early.
	 */
	 */
	atomic_set(&ioend->io_remaining, 1);
	atomic_set(&ioend->io_remaining, 1);
	ioend->io_isasync = 0;
	ioend->io_error = 0;
	ioend->io_error = 0;
	ioend->io_list = NULL;
	ioend->io_list = NULL;
	ioend->io_type = type;
	ioend->io_type = type;
@@ -1289,7 +1293,6 @@ xfs_end_io_direct_write(
	bool			is_async)
	bool			is_async)
{
{
	struct xfs_ioend	*ioend = iocb->private;
	struct xfs_ioend	*ioend = iocb->private;
	struct inode		*inode = ioend->io_inode;


	/*
	/*
	 * blockdev_direct_IO can return an error even after the I/O
	 * 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_offset = offset;
	ioend->io_size = size;
	ioend->io_size = size;
	ioend->io_iocb = iocb;
	ioend->io_result = ret;
	if (private && size > 0)
	if (private && size > 0)
		ioend->io_type = IO_UNWRITTEN;
		ioend->io_type = IO_UNWRITTEN;


	if (is_async) {
	if (is_async) {
		/*
		ioend->io_isasync = 1;
		 * 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);
		}
		xfs_finish_ioend(ioend);
		xfs_finish_ioend(ioend);
	} else {
	} else {
		xfs_finish_ioend_sync(ioend);
		xfs_finish_ioend_sync(ioend);
	}
	}

	/* XXX: probably should move into the real I/O completion handler */
	inode_dio_done(inode);
}
}


STATIC ssize_t
STATIC ssize_t
+1 −0
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ typedef struct xfs_ioend {
	unsigned int		io_type;	/* delalloc / unwritten */
	unsigned int		io_type;	/* delalloc / unwritten */
	int			io_error;	/* I/O error code */
	int			io_error;	/* I/O error code */
	atomic_t		io_remaining;	/* hold count */
	atomic_t		io_remaining;	/* hold count */
	unsigned int		io_isasync : 1;	/* needs aio_complete */
	struct inode		*io_inode;	/* file being written to */
	struct inode		*io_inode;	/* file being written to */
	struct buffer_head	*io_buffer_head;/* buffer linked list head */
	struct buffer_head	*io_buffer_head;/* buffer linked list head */
	struct buffer_head	*io_buffer_tail;/* buffer linked list tail */
	struct buffer_head	*io_buffer_tail;/* buffer linked list tail */