Insert the appropriate uvm_vnp_uncache(9) and uvm_vnp_setsize(9)
authorhelg <helg@openbsd.org>
Mon, 16 Jul 2018 16:44:09 +0000 (16:44 +0000)
committerhelg <helg@openbsd.org>
Mon, 16 Jul 2018 16:44:09 +0000 (16:44 +0000)
kernel calls to ensure that the UVM cache for memory mapped files is
up to date.

ok mpi@

sys/miscfs/fuse/fuse_vfsops.c
sys/miscfs/fuse/fuse_vnops.c
sys/uvm/uvm_vnode.c

index 24bf23f..a7f957f 100644 (file)
@@ -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 <ccna.syl@gmail.com>
  *
@@ -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);
index b20f532..3842718 100644 (file)
@@ -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 <ccna.syl@gmail.com>
  *
@@ -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;
        }
index 8ccfd39..3803d31 100644 (file)
@@ -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