diff options
| author | Alan Somers <asomers@FreeBSD.org> | 2021-11-29 01:53:31 +0000 |
|---|---|---|
| committer | Alan Somers <asomers@FreeBSD.org> | 2021-12-14 22:15:53 +0000 |
| commit | 0bade34633f997c22f5e4e0931df0d534f560a38 (patch) | |
| tree | 8ce6983e469816891271229290a9d9d5a8df366f /sys/fs/fuse | |
| parent | 000ce6dee1fa387d526762f8bc1946d13823312e (diff) | |
| download | src-0bade34633f997c22f5e4e0931df0d534f560a38.tar.gz src-0bade34633f997c22f5e4e0931df0d534f560a38.zip | |
fusefs: update atime on reads when using cached attributes
When using cached attributes, whether or not the data cache is enabled,
fusefs must update a file's atime whenever it reads from it, so long as
it wasn't mounted with -o noatime. Update it in-kernel, and flush it to
the server on close or during the next setattr operation.
The downside is that close() will now frequently trigger a FUSE_SETATTR
upcall. But if you care about performance, you should be using
-o noatime anyway.
Reviewed by: pfg
Differential Revision: https://reviews.freebsd.org/D33145
(cherry picked from commit 91972cfcddf950d7a9c33df5a9171ada1805a144)
fusefs: fix 32-bit build of the tests after 91972cfcddf
(cherry picked from commit d109559ddbf7afe311c1f1795ece137071406db8)
Diffstat (limited to 'sys/fs/fuse')
| -rw-r--r-- | sys/fs/fuse/fuse_internal.c | 11 | ||||
| -rw-r--r-- | sys/fs/fuse/fuse_io.c | 3 | ||||
| -rw-r--r-- | sys/fs/fuse/fuse_node.c | 12 | ||||
| -rw-r--r-- | sys/fs/fuse/fuse_node.h | 3 | ||||
| -rw-r--r-- | sys/fs/fuse/fuse_vnops.c | 10 |
5 files changed, 33 insertions, 6 deletions
diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c index ffa4a40095b2..403116593bd9 100644 --- a/sys/fs/fuse/fuse_internal.c +++ b/sys/fs/fuse/fuse_internal.c @@ -926,6 +926,7 @@ fuse_internal_do_getattr(struct vnode *vp, struct vattr *vap, struct fuse_getattr_in *fgai; struct fuse_attr_out *fao; off_t old_filesize = fvdat->cached_attrs.va_size; + struct timespec old_atime = fvdat->cached_attrs.va_atime; struct timespec old_ctime = fvdat->cached_attrs.va_ctime; struct timespec old_mtime = fvdat->cached_attrs.va_mtime; enum vtype vtyp; @@ -950,6 +951,10 @@ fuse_internal_do_getattr(struct vnode *vp, struct vattr *vap, vtyp = IFTOVT(fao->attr.mode); if (fvdat->flag & FN_SIZECHANGE) fao->attr.size = old_filesize; + if (fvdat->flag & FN_ATIMECHANGE) { + fao->attr.atime = old_atime.tv_sec; + fao->attr.atimensec = old_atime.tv_nsec; + } if (fvdat->flag & FN_CTIMECHANGE) { fao->attr.ctime = old_ctime.tv_sec; fao->attr.ctimensec = old_ctime.tv_nsec; @@ -1209,6 +1214,10 @@ int fuse_internal_setattr(struct vnode *vp, struct vattr *vap, fsai->valid |= FATTR_ATIME; if (vap->va_vaflags & VA_UTIMES_NULL) fsai->valid |= FATTR_ATIME_NOW; + } else if (fvdat->flag & FN_ATIMECHANGE) { + fsai->atime = fvdat->cached_attrs.va_atime.tv_sec; + fsai->atimensec = fvdat->cached_attrs.va_atime.tv_nsec; + fsai->valid |= FATTR_ATIME; } if (vap->va_mtime.tv_sec != VNOVAL) { fsai->mtime = vap->va_mtime.tv_sec; @@ -1257,7 +1266,7 @@ int fuse_internal_setattr(struct vnode *vp, struct vattr *vap, } if (err == 0) { struct fuse_attr_out *fao = (struct fuse_attr_out*)fdi.answ; - fuse_vnode_undirty_cached_timestamps(vp); + fuse_vnode_undirty_cached_timestamps(vp, true); fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid, fao->attr_valid_nsec, NULL, false); } diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c index a240217fcc08..78398a990d7d 100644 --- a/sys/fs/fuse/fuse_io.c +++ b/sys/fs/fuse/fuse_io.c @@ -236,6 +236,7 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag, switch (uio->uio_rw) { case UIO_READ: + fuse_vnode_update(vp, FN_ATIMECHANGE); if (directio) { SDT_PROBE2(fusefs, , io, trace, 1, "direct read of vnode"); @@ -616,7 +617,7 @@ retry: fdisp_destroy(&fdi); if (wrote_anything) - fuse_vnode_undirty_cached_timestamps(vp); + fuse_vnode_undirty_cached_timestamps(vp, false); return (err); } diff --git a/sys/fs/fuse/fuse_node.c b/sys/fs/fuse/fuse_node.c index c8982c5a48a1..f74de2faa702 100644 --- a/sys/fs/fuse/fuse_node.c +++ b/sys/fs/fuse/fuse_node.c @@ -474,11 +474,13 @@ fuse_vnode_size(struct vnode *vp, off_t *filesize, struct ucred *cred, } void -fuse_vnode_undirty_cached_timestamps(struct vnode *vp) +fuse_vnode_undirty_cached_timestamps(struct vnode *vp, bool atime) { struct fuse_vnode_data *fvdat = VTOFUD(vp); fvdat->flag &= ~(FN_MTIMECHANGE | FN_CTIMECHANGE); + if (atime) + fvdat->flag &= ~FN_ATIMECHANGE; } /* Update a fuse file's cached timestamps */ @@ -486,7 +488,8 @@ void fuse_vnode_update(struct vnode *vp, int flags) { struct fuse_vnode_data *fvdat = VTOFUD(vp); - struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); + struct mount *mp = vnode_mount(vp); + struct fuse_data *data = fuse_get_mpdata(mp); struct timespec ts; vfs_timestamp(&ts); @@ -494,6 +497,11 @@ fuse_vnode_update(struct vnode *vp, int flags) if (data->time_gran > 1) ts.tv_nsec = rounddown(ts.tv_nsec, data->time_gran); + if (mp->mnt_flag & MNT_NOATIME) + flags &= ~FN_ATIMECHANGE; + + if (flags & FN_ATIMECHANGE) + fvdat->cached_attrs.va_atime = ts; if (flags & FN_MTIMECHANGE) fvdat->cached_attrs.va_mtime = ts; if (flags & FN_CTIMECHANGE) diff --git a/sys/fs/fuse/fuse_node.h b/sys/fs/fuse/fuse_node.h index 8f69ef9a08f3..3a33c57001dc 100644 --- a/sys/fs/fuse/fuse_node.h +++ b/sys/fs/fuse/fuse_node.h @@ -91,6 +91,7 @@ */ #define FN_MTIMECHANGE 0x00000800 #define FN_CTIMECHANGE 0x00001000 +#define FN_ATIMECHANGE 0x00002000 struct fuse_vnode_data { /** self **/ @@ -201,7 +202,7 @@ int fuse_vnode_savesize(struct vnode *vp, struct ucred *cred, pid_t pid); int fuse_vnode_setsize(struct vnode *vp, off_t newsize, bool from_server); -void fuse_vnode_undirty_cached_timestamps(struct vnode *vp); +void fuse_vnode_undirty_cached_timestamps(struct vnode *vp, bool atime); void fuse_vnode_update(struct vnode *vp, int flags); diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index 5630eeeb9e65..d0f4cae302c1 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -613,6 +613,7 @@ fuse_vnop_close(struct vop_close_args *ap) int fflag = ap->a_fflag; struct thread *td = ap->a_td; pid_t pid = td->td_proc->p_pid; + struct fuse_vnode_data *fvdat = VTOFUD(vp); int err = 0; if (fuse_isdeadfs(vp)) @@ -623,8 +624,15 @@ fuse_vnop_close(struct vop_close_args *ap) return 0; err = fuse_flush(vp, cred, pid, fflag); + if (err == 0 && (fvdat->flag & FN_ATIMECHANGE)) { + struct vattr vap; + + VATTR_NULL(&vap); + vap.va_atime = fvdat->cached_attrs.va_atime; + err = fuse_internal_setattr(vp, &vap, td, NULL); + } /* TODO: close the file handle, if we're sure it's no longer used */ - if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { + if ((fvdat->flag & FN_SIZECHANGE) != 0) { fuse_vnode_savesize(vp, cred, td->td_proc->p_pid); } return err; |
