Skip to content

Commit

Permalink
xfs: ensure correct timestamp updates from truncate
Browse files Browse the repository at this point in the history
The VFS doesn't set the proper ATTR_CTIME and ATTR_MTIME values for
truncate, so filesystems have to manually add them.  The
introduction of xfs_setattr_time accidentally broke this special
case an caused a regression in generic/313.  Fix this by removing
the local mask variable in xfs_setattr_size so that we only have a
single place to keep the attribute information.

cc: <stable@vger.kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Jie Liu <jeff.liu@oracle.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
  • Loading branch information
Christoph Hellwig authored and Dave Chinner committed Feb 9, 2014
1 parent 38dbfb5 commit fe60a8a
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions fs/xfs/xfs_iops.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,6 @@ xfs_setattr_size(
{
struct xfs_mount *mp = ip->i_mount;
struct inode *inode = VFS_I(ip);
int mask = iattr->ia_valid;
xfs_off_t oldsize, newsize;
struct xfs_trans *tp;
int error;
Expand All @@ -726,8 +725,8 @@ xfs_setattr_size(

ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
ASSERT(S_ISREG(ip->i_d.di_mode));
ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);

oldsize = inode->i_size;
newsize = iattr->ia_size;
Expand All @@ -736,7 +735,7 @@ xfs_setattr_size(
* Short circuit the truncate case for zero length files.
*/
if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
return 0;

/*
Expand Down Expand Up @@ -824,10 +823,11 @@ xfs_setattr_size(
* these flags set. For all other operations the VFS set these flags
* explicitly if it wants a timestamp update.
*/
if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
if (newsize != oldsize &&
!(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
iattr->ia_ctime = iattr->ia_mtime =
current_fs_time(inode->i_sb);
mask |= ATTR_CTIME | ATTR_MTIME;
iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
}

/*
Expand Down Expand Up @@ -863,9 +863,9 @@ xfs_setattr_size(
xfs_inode_clear_eofblocks_tag(ip);
}

if (mask & ATTR_MODE)
if (iattr->ia_valid & ATTR_MODE)
xfs_setattr_mode(ip, iattr);
if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
xfs_setattr_time(ip, iattr);

xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
Expand Down

0 comments on commit fe60a8a

Please sign in to comment.