aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-04-16 08:03:27 -0400
committerDave Chinner <david@fromorbit.com>2015-04-16 08:03:27 -0400
commit0cefb29e6a63727bc7606c47fc538467594ef112 (patch)
treee2171e13faac717139a565a6e7268a15aabe4f58 /fs/xfs
parent40c63fbc55a968383b8bb5cacad81585e80cd323 (diff)
xfs: using generic_file_direct_write() is unnecessary
generic_file_direct_write() does all sorts of things to make DIO work "sorta ok" with mixed buffered IO workloads. We already do most of this work in xfs_file_aio_dio_write() because of the locking requirements, so there's only a couple of things it does for us. The first thing is that it does a page cache invalidation after the ->direct_IO callout. This can easily be added to the XFS code. The second thing it does is that if data was written, it updates the iov_iter structure to reflect the data written, and then does EOF size updates if necessary. For XFS, these EOF size updates are now not necessary, as we do them safely and race-free in IO completion context. That leaves just the iov_iter update, and that's also moved to the XFS code. Therefore we don't need to call generic_file_direct_write() and in doing so remove redundant buffered writeback and page cache invalidation calls from the DIO submission path. We also remove a racy EOF size update, and make the DIO submission code in XFS much easier to follow. Wins all round, really. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_file.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f6f0e9671919..79ffb3e74f49 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -659,6 +659,8 @@ xfs_file_dio_aio_write(
659 int iolock; 659 int iolock;
660 size_t count = iov_iter_count(from); 660 size_t count = iov_iter_count(from);
661 loff_t pos = iocb->ki_pos; 661 loff_t pos = iocb->ki_pos;
662 loff_t end;
663 struct iov_iter data;
662 struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ? 664 struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ?
663 mp->m_rtdev_targp : mp->m_ddev_targp; 665 mp->m_rtdev_targp : mp->m_ddev_targp;
664 666
@@ -698,10 +700,11 @@ xfs_file_dio_aio_write(
698 if (ret) 700 if (ret)
699 goto out; 701 goto out;
700 iov_iter_truncate(from, count); 702 iov_iter_truncate(from, count);
703 end = pos + count - 1;
701 704
702 if (mapping->nrpages) { 705 if (mapping->nrpages) {
703 ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, 706 ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
704 pos, pos + count - 1); 707 pos, end);
705 if (ret) 708 if (ret)
706 goto out; 709 goto out;
707 /* 710 /*
@@ -711,7 +714,7 @@ xfs_file_dio_aio_write(
711 */ 714 */
712 ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, 715 ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
713 pos >> PAGE_CACHE_SHIFT, 716 pos >> PAGE_CACHE_SHIFT,
714 (pos + count - 1) >> PAGE_CACHE_SHIFT); 717 end >> PAGE_CACHE_SHIFT);
715 WARN_ON_ONCE(ret); 718 WARN_ON_ONCE(ret);
716 ret = 0; 719 ret = 0;
717 } 720 }
@@ -728,8 +731,22 @@ xfs_file_dio_aio_write(
728 } 731 }
729 732
730 trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); 733 trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0);
731 ret = generic_file_direct_write(iocb, from, pos);
732 734
735 data = *from;
736 ret = mapping->a_ops->direct_IO(WRITE, iocb, &data, pos);
737
738 /* see generic_file_direct_write() for why this is necessary */
739 if (mapping->nrpages) {
740 invalidate_inode_pages2_range(mapping,
741 pos >> PAGE_CACHE_SHIFT,
742 end >> PAGE_CACHE_SHIFT);
743 }
744
745 if (ret > 0) {
746 pos += ret;
747 iov_iter_advance(from, ret);
748 iocb->ki_pos = pos;
749 }
733out: 750out:
734 xfs_rw_iunlock(ip, iolock); 751 xfs_rw_iunlock(ip, iolock);
735 752