提交 17e3abba 编写于 作者: B Brian Foster 提交者: Joseph Qi

xfs: serialize unaligned dio writes against all other dio writes

commit 2032a8a27b5cc0f578d37fa16fa2494b80a0d00a upstream.

XFS applies more strict serialization constraints to unaligned
direct writes to accommodate things like direct I/O layer zeroing,
unwritten extent conversion, etc. Unaligned submissions acquire the
exclusive iolock and wait for in-flight dio to complete to ensure
multiple submissions do not race on the same block and cause data
corruption.

This generally works in the case of an aligned dio followed by an
unaligned dio, but the serialization is lost if I/Os occur in the
opposite order. If an unaligned write is submitted first and
immediately followed by an overlapping, aligned write, the latter
submits without the typical unaligned serialization barriers because
there is no indication of an unaligned dio still in-flight. This can
lead to unpredictable results.

To provide proper unaligned dio serialization, require that such
direct writes are always the only dio allowed in-flight at one time
for a particular inode. We already acquire the exclusive iolock and
drain pending dio before submitting the unaligned dio. Wait once
more after the dio submission to hold the iolock across the I/O and
prevent further submissions until the unaligned I/O completes. This
is heavy handed, but consistent with the current pre-submission
serialization for unaligned direct writes.
Signed-off-by: NBrian Foster <bfoster@redhat.com>
Reviewed-by: NAllison Henderson <allison.henderson@oracle.com>
Reviewed-by: NDave Chinner <dchinner@redhat.com>
Reviewed-by: NDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: NDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: NAlvin Zheng <Alvin@linux.alibaba.com>
Acked-by: NJoseph Qi <joseph.qi@linux.alibaba.com>
上级 da7527a5
...@@ -529,18 +529,17 @@ xfs_file_dio_aio_write( ...@@ -529,18 +529,17 @@ xfs_file_dio_aio_write(
count = iov_iter_count(from); count = iov_iter_count(from);
/* /*
* If we are doing unaligned IO, wait for all other IO to drain, * If we are doing unaligned IO, we can't allow any other overlapping IO
* otherwise demote the lock if we had to take the exclusive lock * in-flight at the same time or we risk data corruption. Wait for all
* for other reasons in xfs_file_aio_write_checks. * other IO to drain before we submit. If the IO is aligned, demote the
* iolock if we had to take the exclusive lock in
* xfs_file_aio_write_checks() for other reasons.
*/ */
if (unaligned_io) { if (unaligned_io) {
/* If we are going to wait for other DIO to finish, bail */ /* unaligned dio always waits, bail */
if (iocb->ki_flags & IOCB_NOWAIT) { if (iocb->ki_flags & IOCB_NOWAIT)
if (atomic_read(&inode->i_dio_count)) return -EAGAIN;
return -EAGAIN; inode_dio_wait(inode);
} else {
inode_dio_wait(inode);
}
} else if (iolock == XFS_IOLOCK_EXCL) { } else if (iolock == XFS_IOLOCK_EXCL) {
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL); xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
iolock = XFS_IOLOCK_SHARED; iolock = XFS_IOLOCK_SHARED;
...@@ -548,6 +547,14 @@ xfs_file_dio_aio_write( ...@@ -548,6 +547,14 @@ xfs_file_dio_aio_write(
trace_xfs_file_direct_write(ip, count, iocb->ki_pos); trace_xfs_file_direct_write(ip, count, iocb->ki_pos);
ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io); ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io);
/*
* If unaligned, this is the only IO in-flight. If it has not yet
* completed, wait on it before we release the iolock to prevent
* subsequent overlapping IO.
*/
if (ret == -EIOCBQUEUED && unaligned_io)
inode_dio_wait(inode);
out: out:
xfs_iunlock(ip, iolock); xfs_iunlock(ip, iolock);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册