diff options
| -rw-r--r-- | fs/xfs/xfs_file.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 1f2e2845eb76..a7ceae90110e 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -529,18 +529,17 @@ xfs_file_dio_aio_write( | |||
| 529 | count = iov_iter_count(from); | 529 | count = iov_iter_count(from); |
| 530 | 530 | ||
| 531 | /* | 531 | /* |
| 532 | * If we are doing unaligned IO, wait for all other IO to drain, | 532 | * If we are doing unaligned IO, we can't allow any other overlapping IO |
| 533 | * otherwise demote the lock if we had to take the exclusive lock | 533 | * in-flight at the same time or we risk data corruption. Wait for all |
| 534 | * for other reasons in xfs_file_aio_write_checks. | 534 | * other IO to drain before we submit. If the IO is aligned, demote the |
| 535 | * iolock if we had to take the exclusive lock in | ||
| 536 | * xfs_file_aio_write_checks() for other reasons. | ||
| 535 | */ | 537 | */ |
| 536 | if (unaligned_io) { | 538 | if (unaligned_io) { |
| 537 | /* If we are going to wait for other DIO to finish, bail */ | 539 | /* unaligned dio always waits, bail */ |
| 538 | if (iocb->ki_flags & IOCB_NOWAIT) { | 540 | if (iocb->ki_flags & IOCB_NOWAIT) |
| 539 | if (atomic_read(&inode->i_dio_count)) | 541 | return -EAGAIN; |
| 540 | return -EAGAIN; | 542 | inode_dio_wait(inode); |
| 541 | } else { | ||
| 542 | inode_dio_wait(inode); | ||
| 543 | } | ||
| 544 | } else if (iolock == XFS_IOLOCK_EXCL) { | 543 | } else if (iolock == XFS_IOLOCK_EXCL) { |
| 545 | xfs_ilock_demote(ip, XFS_IOLOCK_EXCL); | 544 | xfs_ilock_demote(ip, XFS_IOLOCK_EXCL); |
| 546 | iolock = XFS_IOLOCK_SHARED; | 545 | iolock = XFS_IOLOCK_SHARED; |
| @@ -548,6 +547,14 @@ xfs_file_dio_aio_write( | |||
| 548 | 547 | ||
| 549 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos); | 548 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos); |
| 550 | ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io); | 549 | ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io); |
| 550 | |||
| 551 | /* | ||
| 552 | * If unaligned, this is the only IO in-flight. If it has not yet | ||
| 553 | * completed, wait on it before we release the iolock to prevent | ||
| 554 | * subsequent overlapping IO. | ||
| 555 | */ | ||
| 556 | if (ret == -EIOCBQUEUED && unaligned_io) | ||
| 557 | inode_dio_wait(inode); | ||
| 551 | out: | 558 | out: |
| 552 | xfs_iunlock(ip, iolock); | 559 | xfs_iunlock(ip, iolock); |
| 553 | 560 | ||
