]> err.no Git - linux-2.6/commitdiff
[XFS] Fix xfs_splice_write() so appended data gets to disk.
authorDavid Chinner <dgc@sgi.com>
Thu, 7 Sep 2006 04:27:15 +0000 (14:27 +1000)
committerDavid Chatterton <chatz@sgi.com>
Thu, 7 Sep 2006 04:27:15 +0000 (14:27 +1000)
xfs_splice_write() failed to update the on disk inode size when extending
the so when the file was closed the range extended by splice was truncated
off. Hence any region of a file written to by splice would end up as a
hole full of zeros.

SGI-PV: 955939
SGI-Modid: xfs-linux-melb:xfs-kern:26920a

Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: David Chatterton <chatz@sgi.com>
fs/xfs/linux-2.6/xfs_lrw.c

index 110c038910ff39580cabb45cf52f4f504c0b4332..ee788b1cb3641a355219183f9217037d04df2a94 100644 (file)
@@ -391,6 +391,8 @@ xfs_splice_write(
        xfs_inode_t             *ip = XFS_BHVTOI(bdp);
        xfs_mount_t             *mp = ip->i_mount;
        ssize_t                 ret;
+       struct inode            *inode = outfilp->f_mapping->host;
+       xfs_fsize_t             isize;
 
        XFS_STATS_INC(xs_write_calls);
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
@@ -417,6 +419,20 @@ xfs_splice_write(
        if (ret > 0)
                XFS_STATS_ADD(xs_write_bytes, ret);
 
+       isize = i_size_read(inode);
+       if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
+               *ppos = isize;
+
+       if (*ppos > ip->i_d.di_size) {
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+               if (*ppos > ip->i_d.di_size) {
+                       ip->i_d.di_size = *ppos;
+                       i_size_write(inode, *ppos);
+                       ip->i_update_core = 1;
+                       ip->i_update_size = 1;
+               }
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       }
        xfs_iunlock(ip, XFS_IOLOCK_EXCL);
        return ret;
 }