From 3c992bbf9c8a8baba52e588f389f0778e3367980 Mon Sep 17 00:00:00 2001 From: helg Date: Mon, 16 Jul 2018 16:44:09 +0000 Subject: [PATCH] Insert the appropriate uvm_vnp_uncache(9) and uvm_vnp_setsize(9) kernel calls to ensure that the UVM cache for memory mapped files is up to date. ok mpi@ --- sys/miscfs/fuse/fuse_vfsops.c | 14 +++++++++++++- sys/miscfs/fuse/fuse_vnops.c | 30 +++++++++++++++++++++++++++--- sys/uvm/uvm_vnode.c | 10 +++++++--- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/sys/miscfs/fuse/fuse_vfsops.c b/sys/miscfs/fuse/fuse_vfsops.c index 24bf23f4f82..a7f957f01dc 100644 --- a/sys/miscfs/fuse/fuse_vfsops.c +++ b/sys/miscfs/fuse/fuse_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vfsops.c,v 1.40 2018/07/05 15:34:25 mpi Exp $ */ +/* $OpenBSD: fuse_vfsops.c,v 1.41 2018/07/16 16:44:09 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -266,6 +266,7 @@ fusefs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, int fusefs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { + struct vattr vattr; struct fusefs_mnt *fmp; struct fusefs_node *ip; struct vnode *nvp; @@ -314,6 +315,17 @@ retry: if (ino == FUSE_ROOTINO) nvp->v_flag |= VROOT; + /* + * Initialise the file size so that file size changes can be + * detected during file operations. + */ + error = VOP_GETATTR(nvp, &vattr, curproc->p_ucred, curproc); + if (error) { + vrele(nvp); + return (error); + } + ip->filesize = vattr.va_size; + *vpp = nvp; return (0); diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index b20f532ce25..3842718f91f 100644 --- a/sys/miscfs/fuse/fuse_vnops.c +++ b/sys/miscfs/fuse/fuse_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vnops.c,v 1.50 2018/07/16 13:10:53 helg Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.51 2018/07/16 16:44:09 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon * @@ -221,26 +221,38 @@ fusefs_open(void *v) struct vop_open_args *ap; struct fusefs_node *ip; struct fusefs_mnt *fmp; + struct vnode *vp; enum fufh_type fufh_type = FUFH_RDONLY; int flags; int error; int isdir; ap = v; - ip = VTOI(ap->a_vp); + vp = ap->a_vp; + ip = VTOI(vp); fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; if (!fmp->sess_init) return (ENXIO); isdir = 0; - if (ap->a_vp->v_type == VDIR) + if (vp->v_type == VDIR) isdir = 1; else { if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) fufh_type = FUFH_RDWR; else if (ap->a_mode & (FWRITE)) fufh_type = FUFH_WRONLY; + + /* + * Due to possible attribute caching, there is no + * reliable way to determine if the file was modified + * externally (e.g. network file system) so clear the + * UVM cache to ensure that it is not stale. The file + * can still become stale later on read but this will + * satisfy most situations. + */ + uvm_vnp_uncache(vp); } /* already open i think all is ok */ @@ -570,6 +582,12 @@ fusefs_setattr(void *v) goto out; } + /* truncate was successful, let uvm know */ + if (vap->va_size != VNOVAL && vap->va_size != ip->filesize) { + ip->filesize = vap->va_size; + uvm_vnp_setsize(vp, vap->va_size); + } + VN_KNOTE(ap->a_vp, NOTE_ATTRIB); out: @@ -1168,6 +1186,12 @@ fusefs_write(void *v) uio->uio_resid += diff; uio->uio_offset -= diff; + if (uio->uio_offset > ip->filesize) { + ip->filesize = uio->uio_offset; + uvm_vnp_setsize(vp, uio->uio_offset); + } + uvm_vnp_uncache(vp); + fb_delete(fbuf); fbuf = NULL; } diff --git a/sys/uvm/uvm_vnode.c b/sys/uvm/uvm_vnode.c index 8ccfd3980f9..3803d31db7b 100644 --- a/sys/uvm/uvm_vnode.c +++ b/sys/uvm/uvm_vnode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_vnode.c,v 1.102 2018/05/02 02:24:56 visa Exp $ */ +/* $OpenBSD: uvm_vnode.c,v 1.103 2018/07/16 16:44:09 helg Exp $ */ /* $NetBSD: uvm_vnode.c,v 1.36 2000/11/24 20:34:01 chs Exp $ */ /* @@ -1274,6 +1274,8 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t *pps, int npages, int flags, int rw) * then return "text busy" * nfs_open: seems to uncache any file opened with nfs * vn_writechk: if VTEXT vnode and can't uncache return "text busy" + * fusefs_open: uncaches any file that is opened + * fusefs_write: uncaches on every write */ int @@ -1341,8 +1343,10 @@ uvm_vnp_uncache(struct vnode *vp) * us. * * called from: - * => truncate fns (ext2fs_truncate, ffs_truncate, detrunc[msdos]) - * => "write" fns (ext2fs_write, WRITE [ufs/ufs], msdosfs_write, nfs_write) + * => truncate fns (ext2fs_truncate, ffs_truncate, detrunc[msdos], + * fusefs_setattr) + * => "write" fns (ext2fs_write, WRITE [ufs/ufs], msdosfs_write, nfs_write + * fusefs_write) * => ffs_balloc [XXX: why? doesn't WRITE handle?] * => NFS: nfs_loadattrcache, nfs_getattrcache, nfs_setattr * => union fs: union_newsize -- 2.20.1