diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-02-23 14:37:08 +0300 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2015-04-25 00:14:13 +0300 |
commit | 48ca7d78ff4efccbf3d670774d29dd52b7af912d (patch) | |
tree | a4c5b8d74dc27af5f715d6f181e4e3be88c14800 /fs/xfs/xfs_inode.h | |
parent | a69957362258b8932fe4df1433b1fdea8072ba04 (diff) | |
download | linux-48ca7d78ff4efccbf3d670774d29dd52b7af912d.tar.xz |
xfs: ensure truncate forces zeroed blocks to disk
[ Upstream commit 5885ebda878b47c4b4602d4b0410cb4b282af024 ]
A new fsync vs power fail test in xfstests indicated that XFS can
have unreliable data consistency when doing extending truncates that
require block zeroing. The blocks beyond EOF get zeroed in memory,
but we never force those changes to disk before we run the
transaction that extends the file size and exposes those blocks to
userspace. This can result in the blocks not being correctly zeroed
after a crash.
Because in-memory behaviour is correct, tools like fsx don't pick up
any coherency problems - it's not until the filesystem is shutdown
or the system crashes after writing the truncate transaction to the
journal but before the zeroed data in the page cache is flushed that
the issue is exposed.
Fix this by also flushing the dirty data in memory region between
the old size and new size when we've found blocks that need zeroing
in the truncate process.
Reported-by: Liu Bo <bo.li.liu@oracle.com>
cc: <stable@vger.kernel.org>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'fs/xfs/xfs_inode.h')
-rw-r--r-- | fs/xfs/xfs_inode.h | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 9af2882e1f4c..cb6ab0ad91a4 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -379,8 +379,9 @@ int xfs_droplink(struct xfs_trans *, struct xfs_inode *); int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); /* from xfs_file.c */ -int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); -int xfs_iozero(struct xfs_inode *, loff_t, size_t); +int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset, + xfs_fsize_t isize, bool *did_zeroing); +int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count); #define IHOLD(ip) \ |