aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_iops.c')
-rw-r--r--fs/xfs/xfs_iops.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index ce80eeb8faa4..e53a90331422 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -37,6 +37,7 @@
37#include "xfs_da_btree.h" 37#include "xfs_da_btree.h"
38#include "xfs_dir2.h" 38#include "xfs_dir2.h"
39#include "xfs_trans_space.h" 39#include "xfs_trans_space.h"
40#include "xfs_pnfs.h"
40 41
41#include <linux/capability.h> 42#include <linux/capability.h>
42#include <linux/xattr.h> 43#include <linux/xattr.h>
@@ -505,7 +506,7 @@ xfs_setattr_mode(
505 inode->i_mode |= mode & ~S_IFMT; 506 inode->i_mode |= mode & ~S_IFMT;
506} 507}
507 508
508static void 509void
509xfs_setattr_time( 510xfs_setattr_time(
510 struct xfs_inode *ip, 511 struct xfs_inode *ip,
511 struct iattr *iattr) 512 struct iattr *iattr)
@@ -750,6 +751,7 @@ xfs_setattr_size(
750 int error; 751 int error;
751 uint lock_flags = 0; 752 uint lock_flags = 0;
752 uint commit_flags = 0; 753 uint commit_flags = 0;
754 bool did_zeroing = false;
753 755
754 trace_xfs_setattr(ip); 756 trace_xfs_setattr(ip);
755 757
@@ -793,20 +795,16 @@ xfs_setattr_size(
793 return error; 795 return error;
794 796
795 /* 797 /*
796 * 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
797 * 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
798 * 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
799 * the inode to the transaction, because the inode cannot be unlocked 801 * part of the transaction.
800 * 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.
801 */ 805 */
802 if (newsize > oldsize) { 806 if (newsize > oldsize) {
803 /* 807 error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing);
804 * Do the first part of growing a file: zero any data in the
805 * last block that is beyond the old EOF. We need to do this
806 * before the inode is joined to the transaction to modify
807 * i_size.
808 */
809 error = xfs_zero_eof(ip, newsize, oldsize);
810 if (error) 808 if (error)
811 return error; 809 return error;
812 } 810 }
@@ -816,23 +814,18 @@ xfs_setattr_size(
816 * 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
817 * 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
818 * 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
819 * problem. 817 * problem. Note that this includes any block zeroing we did above;
820 * 818 * otherwise those blocks may not be zeroed after a crash.
821 * Only flush from the on disk size to the smaller of the in memory
822 * file size or the new size as that's the range we really care about
823 * here and prevents waiting for other data not within the range we
824 * care about here.
825 */ 819 */
826 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)) {
827 error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, 822 error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
828 ip->i_d.di_size, newsize); 823 ip->i_d.di_size, newsize);
829 if (error) 824 if (error)
830 return error; 825 return error;
831 } 826 }
832 827
833 /* 828 /* Now wait for all direct I/O to complete. */
834 * Wait for all direct I/O to complete.
835 */
836 inode_dio_wait(inode); 829 inode_dio_wait(inode);
837 830
838 /* 831 /*
@@ -979,9 +972,13 @@ xfs_vn_setattr(
979 int error; 972 int error;
980 973
981 if (iattr->ia_valid & ATTR_SIZE) { 974 if (iattr->ia_valid & ATTR_SIZE) {
982 xfs_ilock(ip, XFS_IOLOCK_EXCL); 975 uint iolock = XFS_IOLOCK_EXCL;
983 error = xfs_setattr_size(ip, iattr); 976
984 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 977 xfs_ilock(ip, iolock);
978 error = xfs_break_layouts(dentry->d_inode, &iolock);
979 if (!error)
980 error = xfs_setattr_size(ip, iattr);
981 xfs_iunlock(ip, iolock);
985 } else { 982 } else {
986 error = xfs_setattr_nonsize(ip, iattr, 0); 983 error = xfs_setattr_nonsize(ip, iattr, 0);
987 } 984 }