Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Jun 2019 20:45:32 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r348582 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Message-ID:  <201906032045.x53KjWOw044893@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Mon Jun  3 20:45:32 2019
New Revision: 348582
URL: https://svnweb.freebsd.org/changeset/base/348582

Log:
  fusefs: don't require FUSE_EXPORT_SUPPORT for async invalidation
  
  In r348560 I thought that FUSE_EXPORT_SUPPORT was required for cases where
  the node to be invalidated (or the parent of the entry to be invalidated)
  wasn't cached.  But I realize now that that's not the case.  During entry
  invalidation, if the parent isn't in the vfs hash table, then it must've
  been reclaimed.  And since fuse_vnop_reclaim does a cache_purge, that means
  the entry to be invalidated has already been removed from the namecache.
  And during inode invalidation, if the inode to be invalidated isn't in the
  vfs hash table, then it too must've been reclaimed.  In that case it will
  have no buffer cache to invalidate.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_internal.c
  projects/fuse2/sys/fs/fuse/fuse_vfsops.c
  projects/fuse2/tests/sys/fs/fusefs/notify.cc

Modified: projects/fuse2/sys/fs/fuse/fuse_internal.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_internal.c	Mon Jun  3 20:40:32 2019	(r348581)
+++ projects/fuse2/sys/fs/fuse/fuse_internal.c	Mon Jun  3 20:45:32 2019	(r348582)
@@ -364,31 +364,17 @@ fuse_internal_fsync(struct vnode *vp,
 }
 
 /* Asynchronous invalidation */
-SDT_PROBE_DEFINE1(fusefs, , internal, invalidate_without_export,
-	"struct mount*");
 SDT_PROBE_DEFINE2(fusefs, , internal, invalidate_cache_hit,
 	"struct vnode*", "struct vnode*");
 int
 fuse_internal_invalidate_entry(struct mount *mp, struct uio *uio)
 {
 	struct fuse_notify_inval_entry_out fnieo;
-	struct fuse_data *data = fuse_get_mpdata(mp);
 	struct componentname cn;
 	struct vnode *dvp, *vp;
 	char name[PATH_MAX];
 	int err;
 
-	if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) {
-		/* 
-		 * Linux allows file systems without export support to use
-		 * asynchronous notification because its inode cache is indexed
-		 * purely by the inode number.  But FreeBSD's vnode is cache
-		 * requires access to the entire vnode structure.
-		 */
-		SDT_PROBE1(fusefs, , internal, invalidate_without_export, mp);
-		return (EINVAL);
-	}
-
 	if ((err = uiomove(&fnieo, sizeof(fnieo), uio)) != 0)
 		return (err);
 
@@ -405,6 +391,11 @@ fuse_internal_invalidate_entry(struct mount *mp, struc
 	else
 		err = fuse_internal_get_cached_vnode( mp, fnieo.parent,
 			LK_SHARED, &dvp);
+	/* 
+	 * If dvp is not in the cache, then it must've been reclaimed.  And
+	 * since fuse_vnop_reclaim does a cache_purge, name's entry must've
+	 * been invalidated already.  So we can safely return if dvp == NULL
+	 */
 	if (err != 0 || dvp == NULL)
 		return (err);
 	/*
@@ -432,20 +423,8 @@ int
 fuse_internal_invalidate_inode(struct mount *mp, struct uio *uio)
 {
 	struct fuse_notify_inval_inode_out fniio;
-	struct fuse_data *data = fuse_get_mpdata(mp);
 	struct vnode *vp;
 	int err;
-
-	if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) {
-		/* 
-		 * Linux allows file systems without export support to use
-		 * asynchronous notification because its inode cache is indexed
-		 * purely by the inode number.  But FreeBSD's vnode is cache
-		 * requires access to the entire vnode structure.
-		 */
-		SDT_PROBE1(fusefs, , internal, invalidate_without_export, mp);
-		return (EINVAL);
-	}
 
 	if ((err = uiomove(&fniio, sizeof(fniio), uio)) != 0)
 		return (err);

Modified: projects/fuse2/sys/fs/fuse/fuse_vfsops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vfsops.c	Mon Jun  3 20:40:32 2019	(r348581)
+++ projects/fuse2/sys/fs/fuse/fuse_vfsops.c	Mon Jun  3 20:45:32 2019	(r348582)
@@ -519,9 +519,12 @@ alreadydead:
 	return 0;
 }
 
+SDT_PROBE_DEFINE1(fusefs, , vfsops, invalidate_without_export,
+	"struct mount*");
 static int
 fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
 {
+	struct fuse_data *data = fuse_get_mpdata(mp);
 	uint64_t nodeid = ino;
 	struct thread *td = curthread;
 	struct fuse_dispatcher fdi;
@@ -531,6 +534,15 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags
 	off_t filesize;
 	enum vtype vtyp;
 	int error;
+
+	if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) {
+		/*
+		 * Unreachable unless you do something stupid, like export a
+		 * nullfs mount of a fusefs file system.
+		 */
+		SDT_PROBE1(fusefs, , vfsops, invalidate_without_export, mp);
+		return (EOPNOTSUPP);
+	}
 
 	error = fuse_internal_get_cached_vnode(mp, ino, flags, vpp);
 	if (error || *vpp != NULL)

Modified: projects/fuse2/tests/sys/fs/fusefs/notify.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/notify.cc	Mon Jun  3 20:40:32 2019	(r348581)
+++ projects/fuse2/tests/sys/fs/fusefs/notify.cc	Mon Jun  3 20:45:32 2019	(r348582)
@@ -50,11 +50,6 @@ using namespace testing;
 
 class Notify: public FuseTest {
 public:
-virtual void SetUp() {
-	m_init_flags = FUSE_EXPORT_SUPPORT;
-	FuseTest::SetUp();
-}
-
 void expect_lookup(uint64_t parent, const char *relpath, uint64_t ino,
 	off_t size, Sequence &seq)
 {



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