diff options
Diffstat (limited to 'fs/xfs/xfs_iops.c')
| -rw-r--r-- | fs/xfs/xfs_iops.c | 36 | 
1 files changed, 14 insertions, 22 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index d919ad7b16bf..e53a90331422 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c  | |||
| @@ -751,6 +751,7 @@ xfs_setattr_size( | |||
| 751 | int error; | 751 | int error; | 
| 752 | uint lock_flags = 0; | 752 | uint lock_flags = 0; | 
| 753 | uint commit_flags = 0; | 753 | uint commit_flags = 0; | 
| 754 | bool did_zeroing = false; | ||
| 754 | 755 | ||
| 755 | trace_xfs_setattr(ip); | 756 | trace_xfs_setattr(ip); | 
| 756 | 757 | ||
| @@ -794,20 +795,16 @@ xfs_setattr_size( | |||
| 794 | return error; | 795 | return error; | 
| 795 | 796 | ||
| 796 | /* | 797 | /* | 
| 797 | * Now we can make the changes. Before we join the inode to the | 798 | * File data changes must be complete before we start the transaction to | 
| 798 | * transaction, take care of the part of the truncation that must be | 799 | * modify the inode. This needs to be done before joining the inode to | 
| 799 | * done without the inode lock. This needs to be done before joining | 800 | * the transaction because the inode cannot be unlocked once it is a | 
| 800 | * the inode to the transaction, because the inode cannot be unlocked | 801 | * part of the transaction. | 
| 801 | * once it is a part of the transaction. | 802 | * | 
| 803 | * Start with zeroing any data block beyond EOF that we may expose on | ||
| 804 | * file extension. | ||
| 802 | */ | 805 | */ | 
| 803 | if (newsize > oldsize) { | 806 | if (newsize > oldsize) { | 
| 804 | /* | 807 | error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing); | 
| 805 | * Do the first part of growing a file: zero any data in the | ||
| 806 | * last block that is beyond the old EOF. We need to do this | ||
| 807 | * before the inode is joined to the transaction to modify | ||
| 808 | * i_size. | ||
| 809 | */ | ||
| 810 | error = xfs_zero_eof(ip, newsize, oldsize); | ||
| 811 | if (error) | 808 | if (error) | 
| 812 | return error; | 809 | return error; | 
| 813 | } | 810 | } | 
| @@ -817,23 +814,18 @@ xfs_setattr_size( | |||
| 817 | * any previous writes that are beyond the on disk EOF and the new | 814 | * any previous writes that are beyond the on disk EOF and the new | 
| 818 | * EOF that have not been written out need to be written here. If we | 815 | * EOF that have not been written out need to be written here. If we | 
| 819 | * do not write the data out, we expose ourselves to the null files | 816 | * do not write the data out, we expose ourselves to the null files | 
| 820 | * problem. | 817 | * problem. Note that this includes any block zeroing we did above; | 
| 821 | * | 818 | * otherwise those blocks may not be zeroed after a crash. | 
| 822 | * Only flush from the on disk size to the smaller of the in memory | ||
| 823 | * file size or the new size as that's the range we really care about | ||
| 824 | * here and prevents waiting for other data not within the range we | ||
| 825 | * care about here. | ||
| 826 | */ | 819 | */ | 
| 827 | if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) { | 820 | if (newsize > ip->i_d.di_size && | 
| 821 | (oldsize != ip->i_d.di_size || did_zeroing)) { | ||
| 828 | error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, | 822 | error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, | 
| 829 | ip->i_d.di_size, newsize); | 823 | ip->i_d.di_size, newsize); | 
| 830 | if (error) | 824 | if (error) | 
| 831 | return error; | 825 | return error; | 
| 832 | } | 826 | } | 
| 833 | 827 | ||
| 834 | /* | 828 | /* Now wait for all direct I/O to complete. */ | 
| 835 | * Wait for all direct I/O to complete. | ||
| 836 | */ | ||
| 837 | inode_dio_wait(inode); | 829 | inode_dio_wait(inode); | 
| 838 | 830 | ||
| 839 | /* | 831 | /* | 
