Skip to content

Commit

Permalink
[XFS] Fix inode size update before data write in xfs_setattr
Browse files Browse the repository at this point in the history
When changing the file size by a truncate() call, we log the change in the
inode size. However, we do not flush any outstanding data that might not
have been written to disk, thereby violating the data/inode size update
order. This can leave files full of NULLs on crash.

Hence if we are truncating the file, flush any unwritten data that may lie
between the curret on disk inode size and the new inode size that is being
logged to ensure that ordering is preserved.

SGI-PV: 966308
SGI-Modid: xfs-linux-melb:xfs-kern:29174a

Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tim Shimmin <tes@sgi.com>
  • Loading branch information
David Chinner authored and Tim Shimmin committed Jul 19, 2007
1 parent 91ebecc commit c32676e
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion fs/xfs/xfs_vnodeops.c
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,30 @@ xfs_setattr(
code = xfs_igrow_start(ip, vap->va_size, credp);
}
xfs_iunlock(ip, XFS_ILOCK_EXCL);
vn_iowait(vp); /* wait for the completion of any pending DIOs */

/*
* We are going to log the inode size change in this
* transaction so any previous writes that are beyond the on
* disk EOF and the new EOF that have not been written out need
* to be written here. If we do not write the data out, we
* expose ourselves to the null files problem.
*
* Only flush from the on disk size to the smaller of the in
* memory file size or the new size as that's the range we
* really care about here and prevents waiting for other data
* not within the range we care about here.
*/
if (!code &&
(ip->i_size != ip->i_d.di_size) &&
(vap->va_size > ip->i_d.di_size)) {
code = bhv_vop_flush_pages(XFS_ITOV(ip),
ip->i_d.di_size, vap->va_size,
XFS_B_ASYNC, FI_NONE);
}

/* wait for all I/O to complete */
vn_iowait(vp);

if (!code)
code = xfs_itruncate_data(ip, vap->va_size);
if (code) {
Expand Down

0 comments on commit c32676e

Please sign in to comment.