On Sun, Nov 24, 2019 at 09:31:45PM +0200, Amir Goldstein wrote:
Push clamping timestamps down the call stack into notify_change(), so in-kernel callers like nfsd and overlayfs will get similar timestamp set behavior as utimes.
So, nfsd has always bypassed timestamp_truncate() and we've never noticed till now? What are the symptoms? (Do timestamps go backwards after cache eviction on filesystems with large time granularity?)
Looks like generic/402 has never run in my tests:
generic/402 [not run] no kernel support for y2038 sysfs switch
--b.
Suggested-by: Miklos Szeredi mszeredi@redhat.com Fixes: 42e729b9ddbb ("utimes: Clamp the timestamps before update") Cc: stable@vger.kernel.org # v5.4 Cc: Deepa Dinamani deepa.kernel@gmail.com Cc: Jeff Layton jlayton@kernel.org Signed-off-by: Amir Goldstein amir73il@gmail.com
Arnd,
This fixes xfstest generic/402 when run with -overlay setup. Note that running the test requires latest xfstests with: acb2ba78 - overlay: support timestamp range check
I had previously posted a fix specific for overlayfs [1], but Miklos suggested this more generic fix, which should also serve nfsd and other in-kernel users.
I tested this change with test generic/402 on ext4/xfs/btrfs and overlayfs, but not with nfsd.
Jeff, could you ack this change is good for nfsd as well?
Thanks, Amir.
[1] https://lore.kernel.org/linux-fsdevel/20191111073000.2957-1-amir73il@gmail.c...
fs/attr.c | 5 +++++ fs/utimes.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/attr.c b/fs/attr.c index df28035aa23e..e8de5e636e66 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -268,8 +268,13 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de attr->ia_ctime = now; if (!(ia_valid & ATTR_ATIME_SET)) attr->ia_atime = now;
- else
if (!(ia_valid & ATTR_MTIME_SET)) attr->ia_mtime = now;attr->ia_atime = timestamp_truncate(attr->ia_atime, inode);
- else
attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode);
- if (ia_valid & ATTR_KILL_PRIV) { error = security_inode_need_killpriv(dentry); if (error < 0)
diff --git a/fs/utimes.c b/fs/utimes.c index 1ba3f7883870..090739322463 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -36,14 +36,14 @@ static int utimes_common(const struct path *path, struct timespec64 *times) if (times[0].tv_nsec == UTIME_OMIT) newattrs.ia_valid &= ~ATTR_ATIME; else if (times[0].tv_nsec != UTIME_NOW) {
newattrs.ia_atime = timestamp_truncate(times[0], inode);
}newattrs.ia_atime = times[0]; newattrs.ia_valid |= ATTR_ATIME_SET;
if (times[1].tv_nsec == UTIME_OMIT) newattrs.ia_valid &= ~ATTR_MTIME; else if (times[1].tv_nsec != UTIME_NOW) {
newattrs.ia_mtime = timestamp_truncate(times[1], inode);
} /*newattrs.ia_mtime = times[1]; newattrs.ia_valid |= ATTR_MTIME_SET;
-- 2.17.1