Commit:     c32676eea19ce29cb74dba0f97b085e83f6b8915
Parent:     91ebecc74eeeeea0a2aa50bf1964ec2214a229c9
Author:     David Chinner <[EMAIL PROTECTED]>
AuthorDate: Thu Jul 19 16:28:58 2007 +1000
Committer:  Tim Shimmin <[EMAIL PROTECTED]>
CommitDate: Thu Jul 19 19:52:05 2007 +1000

    [XFS] Fix inode size update before data write in xfs_setattr
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>
    Signed-off-by: Tim Shimmin <[EMAIL PROTECTED]>
 fs/xfs/xfs_vnodeops.c |   25 ++++++++++++++++++++++++-
 1 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 401cb00..1a5ad8c 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -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) {
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to