From 0a8fe2d3697ef841ccfd03f0a1f66e6d5abe77ad Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Wed, 26 Jun 2019 00:03:37 +0000 Subject: [PATCH] fusefs: set ctime during FUSE_SETATTR following a write As of r349396 the kernel will internally update the mtime and ctime of files on write. It will also flush the mtime should a SETATTR happen before the data cache gets flushed. Now it will flush the ctime too, if the server is using protocol 7.23 or higher. This is the only case in which the kernel will explicitly set a file's ctime, since neither utimensat(2) nor any other user interfaces allow it. Sponsored by: The FreeBSD Foundation --- sys/fs/fuse/fuse_internal.c | 5 +++++ tests/sys/fs/fusefs/write.cc | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c index 933bc7aa65c4..5df6e18444ca 100644 --- a/sys/fs/fuse/fuse_internal.c +++ b/sys/fs/fuse/fuse_internal.c @@ -1074,6 +1074,11 @@ int fuse_internal_setattr(struct vnode *vp, struct vattr *vap, fsai->mtimensec = fvdat->cached_attrs.va_mtime.tv_nsec; fsai->valid |= FATTR_MTIME; } + if (fuse_libabi_geq(data, 7, 23) && fvdat->flag & FN_CTIMECHANGE) { + fsai->ctime = fvdat->cached_attrs.va_ctime.tv_sec; + fsai->ctimensec = fvdat->cached_attrs.va_ctime.tv_nsec; + fsai->valid |= FATTR_CTIME; + } if (vap->va_mode != (mode_t)VNOVAL) { fsai->mode = vap->va_mode & ALLPERMS; fsai->valid |= FATTR_MODE; diff --git a/tests/sys/fs/fusefs/write.cc b/tests/sys/fs/fusefs/write.cc index 3dd6e1cf3991..147027d1b0ae 100644 --- a/tests/sys/fs/fusefs/write.cc +++ b/tests/sys/fs/fusefs/write.cc @@ -1117,8 +1117,7 @@ TEST_F(WriteBackAsync, timestamps_during_setattr) expect_open(ino, 0, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { - /* In protocol 7.23, ctime will be changed too */ - uint32_t valid = FATTR_MODE | FATTR_MTIME; + uint32_t valid = FATTR_MODE | FATTR_MTIME | FATTR_CTIME; return (in.header.opcode == FUSE_SETATTR && in.header.nodeid == ino && in.body.setattr.valid == valid);