OSDN Git Service

[XFS] Update c/mtime correctly on truncates
authorDavid Chinner <dgc@sgi.com>
Thu, 6 Mar 2008 02:45:29 +0000 (13:45 +1100)
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>
Fri, 18 Apr 2008 01:39:45 +0000 (11:39 +1000)
XFS changes the c/mtime of an inode when truncating it to the same size.
The c/mtime is only supposed to change if the size is changed. Not to be
confused with ftruncate, where the c/mtime is supposed to be changed even
if the size is not changed.

The Linux VFS encodes this semantic difference in the flags it sends down
to ->setattr, which XFS currently ignores. We need to make XFS pay
attention to the VFS flags and hence Do The Right Thing.

SGI-PV: 977547
SGI-Modid: xfs-linux-melb:xfs-kern:30536a

Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
fs/xfs/xfs_vnodeops.c

index 811ee87..b77dede 100644 (file)
@@ -633,6 +633,15 @@ xfs_setattr(
         * Truncate file.  Must have write permission and not be a directory.
         */
        if (mask & XFS_AT_SIZE) {
+               /*
+                * Only change the c/mtime if we are changing the size
+                * or we are explicitly asked to change it. This handles
+                * the semantic difference between truncate() and ftruncate()
+                * as implemented in the VFS.
+                */
+               if (vap->va_size != ip->i_size || (mask & XFS_AT_CTIME))
+                       timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
+
                if (vap->va_size > ip->i_size) {
                        xfs_igrow_finish(tp, ip, vap->va_size,
                            !(flags & ATTR_DMI));
@@ -661,10 +670,6 @@ xfs_setattr(
                         */
                        xfs_iflags_set(ip, XFS_ITRUNCATED);
                }
-               /*
-                * Have to do this even if the file's size doesn't change.
-                */
-               timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
        }
 
        /*