Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Feb 2019 22:50:31 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r344184 - head/sys/fs/fuse
Message-ID:  <201902152250.x1FMoVk8013356@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Fri Feb 15 22:50:31 2019
New Revision: 344184
URL: https://svnweb.freebsd.org/changeset/base/344184

Log:
  FUSE: Respect userspace FS "do-not-cache" of path components
  
  The FUSE protocol demands that kernel implementations cache user filesystem
  path components (lookup/cnp data) for a maximum period of time in the range
  of [0, ULONG_MAX] seconds.  In practice, typical requests are for 0, 1, or
  10 seconds; or "a long time" to represent indefinite caching.
  
  Historically, FreeBSD FUSE has ignored this client directive entirely.  This
  works fine for local-only filesystems, but causes consistency issues with
  multi-writer network filesystems.
  
  For now, respect 0 second cache TTLs and do not cache such metadata.
  Non-zero metadata caching TTLs in the range [0.000000001, ULONG_MAX] seconds
  are still cached indefinitely, because it is unclear how a userspace
  filesystem could do anything sensible with those semantics even if
  implemented.
  
  Pass fuse_entry_out to fuse_vnode_get when available and only cache lookup
  if the user filesystem did not set a zero second TTL.
  
  PR:		230258 (inspired by; does not fix)

Modified:
  head/sys/fs/fuse/fuse_internal.c
  head/sys/fs/fuse/fuse_node.c
  head/sys/fs/fuse/fuse_node.h
  head/sys/fs/fuse/fuse_vfsops.c
  head/sys/fs/fuse/fuse_vnops.c

Modified: head/sys/fs/fuse/fuse_internal.c
==============================================================================
--- head/sys/fs/fuse/fuse_internal.c	Fri Feb 15 22:49:15 2019	(r344183)
+++ head/sys/fs/fuse/fuse_internal.c	Fri Feb 15 22:50:31 2019	(r344184)
@@ -471,7 +471,7 @@ fuse_internal_newentry_core(struct vnode *dvp,
 	if ((err = fuse_internal_checkentry(feo, vtyp))) {
 		return err;
 	}
-	err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, vtyp);
+	err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, vtyp);
 	if (err) {
 		fuse_internal_forget_send(mp, cnp->cn_thread, cnp->cn_cred,
 		    feo->nodeid, 1);

Modified: head/sys/fs/fuse/fuse_node.c
==============================================================================
--- head/sys/fs/fuse/fuse_node.c	Fri Feb 15 22:49:15 2019	(r344183)
+++ head/sys/fs/fuse/fuse_node.c	Fri Feb 15 22:50:31 2019	(r344184)
@@ -241,6 +241,7 @@ fuse_vnode_alloc(struct mount *mp,
 
 int
 fuse_vnode_get(struct mount *mp,
+    struct fuse_entry_out *feo,
     uint64_t nodeid,
     struct vnode *dvp,
     struct vnode **vpp,
@@ -261,7 +262,9 @@ fuse_vnode_get(struct mount *mp,
 		MPASS(!(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.'));
 		fuse_vnode_setparent(*vpp, dvp);
 	}
-	if (dvp != NULL && cnp != NULL && (cnp->cn_flags & MAKEENTRY) != 0) {
+	if (dvp != NULL && cnp != NULL && (cnp->cn_flags & MAKEENTRY) != 0 &&
+	    feo != NULL &&
+	    (feo->entry_valid != 0 || feo->entry_valid_nsec != 0)) {
 		ASSERT_VOP_LOCKED(*vpp, "fuse_vnode_get");
 		ASSERT_VOP_LOCKED(dvp, "fuse_vnode_get");
 		cache_enter(dvp, *vpp, cnp);

Modified: head/sys/fs/fuse/fuse_node.h
==============================================================================
--- head/sys/fs/fuse/fuse_node.h	Fri Feb 15 22:49:15 2019	(r344183)
+++ head/sys/fs/fuse/fuse_node.h	Fri Feb 15 22:50:31 2019	(r344184)
@@ -117,6 +117,7 @@ fuse_vnode_setparent(struct vnode *vp, struct vnode *d
 void fuse_vnode_destroy(struct vnode *vp);
 
 int fuse_vnode_get(struct mount         *mp,
+                   struct fuse_entry_out *feo,
                    uint64_t              nodeid,
                    struct vnode         *dvp,
                    struct vnode        **vpp,

Modified: head/sys/fs/fuse/fuse_vfsops.c
==============================================================================
--- head/sys/fs/fuse/fuse_vfsops.c	Fri Feb 15 22:49:15 2019	(r344183)
+++ head/sys/fs/fuse/fuse_vfsops.c	Fri Feb 15 22:50:31 2019	(r344184)
@@ -444,7 +444,8 @@ fuse_vfsop_root(struct mount *mp, int lkflags, struct 
 		if (err == 0)
 			*vpp = data->vroot;
 	} else {
-		err = fuse_vnode_get(mp, FUSE_ROOT_ID, NULL, vpp, NULL, VDIR);
+		err = fuse_vnode_get(mp, NULL, FUSE_ROOT_ID, NULL, vpp, NULL,
+		    VDIR);
 		if (err == 0) {
 			FUSE_LOCK();
 			MPASS(data->vroot == NULL || data->vroot == *vpp);

Modified: head/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- head/sys/fs/fuse/fuse_vnops.c	Fri Feb 15 22:49:15 2019	(r344183)
+++ head/sys/fs/fuse/fuse_vnops.c	Fri Feb 15 22:50:31 2019	(r344184)
@@ -384,7 +384,7 @@ fuse_vnop_create(struct vop_create_args *ap)
 	if ((err = fuse_internal_checkentry(feo, VREG))) {
 		goto out;
 	}
-	err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, VREG);
+	err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, VREG);
 	if (err) {
 		struct fuse_release_in *fri;
 		uint64_t nodeid = feo->nodeid;
@@ -857,8 +857,8 @@ calldaemon:
 				vref(dvp);
 				*vpp = dvp;
 			} else {
-				err = fuse_vnode_get(dvp->v_mount, nid, dvp,
-				    &vp, cnp, IFTOVT(fattr->mode));
+				err = fuse_vnode_get(dvp->v_mount, feo, nid,
+				    dvp, &vp, cnp, IFTOVT(fattr->mode));
 				if (err)
 					goto out;
 				*vpp = vp;
@@ -893,12 +893,8 @@ calldaemon:
 				err = EISDIR;
 				goto out;
 			}
-			err = fuse_vnode_get(vnode_mount(dvp),
-			    nid,
-			    dvp,
-			    &vp,
-			    cnp,
-			    IFTOVT(fattr->mode));
+			err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
+			    &vp, cnp, IFTOVT(fattr->mode));
 			if (err) {
 				goto out;
 			}
@@ -936,12 +932,8 @@ calldaemon:
 				}
 			}
 			VOP_UNLOCK(dvp, 0);
-			err = fuse_vnode_get(vnode_mount(dvp),
-			    nid,
-			    NULL,
-			    &vp,
-			    cnp,
-			    IFTOVT(fattr->mode));
+			err = fuse_vnode_get(vnode_mount(dvp), feo, nid, NULL,
+			    &vp, cnp, IFTOVT(fattr->mode));
 			vfs_unbusy(mp);
 			vn_lock(dvp, ltype | LK_RETRY);
 			if ((dvp->v_iflag & VI_DOOMED) != 0) {
@@ -956,12 +948,8 @@ calldaemon:
 			vref(dvp);
 			*vpp = dvp;
 		} else {
-			err = fuse_vnode_get(vnode_mount(dvp),
-			    nid,
-			    dvp,
-			    &vp,
-			    cnp,
-			    IFTOVT(fattr->mode));
+			err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
+			    &vp, cnp, IFTOVT(fattr->mode));
 			if (err) {
 				goto out;
 			}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902152250.x1FMoVk8013356>