diff options
author | Christoph Hellwig <hch@lst.de> | 2016-06-20 19:52:47 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-06-20 19:52:47 -0400 |
commit | f0c6bcba74ac51cb77aadb33ad35cb2dc1ad1506 (patch) | |
tree | c4674d611e81f13021becc33e08ebd2a411d47c4 | |
parent | 3b3dce05279b97525741b7949208017307e05621 (diff) |
xfs: reorder zeroing and flushing sequence in truncate
Currently zeroing out blocks and waiting for writeout is a bit of a mess in
truncate. This patch gives it a clear order in preparation for the iomap
path:
(1) we first wait for any direct I/O to complete to prevent any races
for it
(2) we then perform the actual zeroing, and only use the truncate_page
helpers for truncating down. The truncate up case already is
handled by the separate call to xfs_zero_eof.
(3) only then we write back dirty data, as zeroing block may cause
dirty pages when using either xfs_zero_eof or the new iomap
infrastructure.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r-- | fs/xfs/xfs_iops.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index c5d4eba6972e..1a5ca4b4a866 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -801,20 +801,35 @@ xfs_setattr_size( | |||
801 | return error; | 801 | return error; |
802 | 802 | ||
803 | /* | 803 | /* |
804 | * Wait for all direct I/O to complete. | ||
805 | */ | ||
806 | inode_dio_wait(inode); | ||
807 | |||
808 | /* | ||
804 | * File data changes must be complete before we start the transaction to | 809 | * File data changes must be complete before we start the transaction to |
805 | * modify the inode. This needs to be done before joining the inode to | 810 | * modify the inode. This needs to be done before joining the inode to |
806 | * the transaction because the inode cannot be unlocked once it is a | 811 | * the transaction because the inode cannot be unlocked once it is a |
807 | * part of the transaction. | 812 | * part of the transaction. |
808 | * | 813 | * |
809 | * Start with zeroing any data block beyond EOF that we may expose on | 814 | * Start with zeroing any data beyond EOF that we may expose on file |
810 | * file extension. | 815 | * extension, or zeroing out the rest of the block on a downward |
816 | * truncate. | ||
811 | */ | 817 | */ |
812 | if (newsize > oldsize) { | 818 | if (newsize > oldsize) { |
813 | error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing); | 819 | error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing); |
814 | if (error) | 820 | } else { |
815 | return error; | 821 | if (IS_DAX(inode)) { |
822 | error = dax_truncate_page(inode, newsize, | ||
823 | xfs_get_blocks_direct); | ||
824 | } else { | ||
825 | error = block_truncate_page(inode->i_mapping, newsize, | ||
826 | xfs_get_blocks); | ||
827 | } | ||
816 | } | 828 | } |
817 | 829 | ||
830 | if (error) | ||
831 | return error; | ||
832 | |||
818 | /* | 833 | /* |
819 | * We are going to log the inode size change in this transaction so | 834 | * We are going to log the inode size change in this transaction so |
820 | * any previous writes that are beyond the on disk EOF and the new | 835 | * any previous writes that are beyond the on disk EOF and the new |
@@ -831,9 +846,6 @@ xfs_setattr_size( | |||
831 | return error; | 846 | return error; |
832 | } | 847 | } |
833 | 848 | ||
834 | /* Now wait for all direct I/O to complete. */ | ||
835 | inode_dio_wait(inode); | ||
836 | |||
837 | /* | 849 | /* |
838 | * We've already locked out new page faults, so now we can safely remove | 850 | * We've already locked out new page faults, so now we can safely remove |
839 | * pages from the page cache knowing they won't get refaulted until we | 851 | * pages from the page cache knowing they won't get refaulted until we |
@@ -851,13 +863,6 @@ xfs_setattr_size( | |||
851 | * to hope that the caller sees ENOMEM and retries the truncate | 863 | * to hope that the caller sees ENOMEM and retries the truncate |
852 | * operation. | 864 | * operation. |
853 | */ | 865 | */ |
854 | if (IS_DAX(inode)) | ||
855 | error = dax_truncate_page(inode, newsize, xfs_get_blocks_direct); | ||
856 | else | ||
857 | error = block_truncate_page(inode->i_mapping, newsize, | ||
858 | xfs_get_blocks); | ||
859 | if (error) | ||
860 | return error; | ||
861 | truncate_setsize(inode, newsize); | 866 | truncate_setsize(inode, newsize); |
862 | 867 | ||
863 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); | 868 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); |