1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

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
This commit is contained in:
Alan Somers 2019-06-03 20:45:32 +00:00
parent eae1ae132c
commit 6ff7f297f8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=348582
3 changed files with 17 additions and 31 deletions

View File

@ -364,31 +364,17 @@ fuse_internal_fsync(struct vnode *vp,
} }
/* Asynchronous invalidation */ /* Asynchronous invalidation */
SDT_PROBE_DEFINE1(fusefs, , internal, invalidate_without_export,
"struct mount*");
SDT_PROBE_DEFINE2(fusefs, , internal, invalidate_cache_hit, SDT_PROBE_DEFINE2(fusefs, , internal, invalidate_cache_hit,
"struct vnode*", "struct vnode*"); "struct vnode*", "struct vnode*");
int int
fuse_internal_invalidate_entry(struct mount *mp, struct uio *uio) fuse_internal_invalidate_entry(struct mount *mp, struct uio *uio)
{ {
struct fuse_notify_inval_entry_out fnieo; struct fuse_notify_inval_entry_out fnieo;
struct fuse_data *data = fuse_get_mpdata(mp);
struct componentname cn; struct componentname cn;
struct vnode *dvp, *vp; struct vnode *dvp, *vp;
char name[PATH_MAX]; char name[PATH_MAX];
int err; 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) if ((err = uiomove(&fnieo, sizeof(fnieo), uio)) != 0)
return (err); return (err);
@ -405,6 +391,11 @@ fuse_internal_invalidate_entry(struct mount *mp, struct uio *uio)
else else
err = fuse_internal_get_cached_vnode( mp, fnieo.parent, err = fuse_internal_get_cached_vnode( mp, fnieo.parent,
LK_SHARED, &dvp); 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) if (err != 0 || dvp == NULL)
return (err); return (err);
/* /*
@ -432,21 +423,9 @@ int
fuse_internal_invalidate_inode(struct mount *mp, struct uio *uio) fuse_internal_invalidate_inode(struct mount *mp, struct uio *uio)
{ {
struct fuse_notify_inval_inode_out fniio; struct fuse_notify_inval_inode_out fniio;
struct fuse_data *data = fuse_get_mpdata(mp);
struct vnode *vp; struct vnode *vp;
int err; 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) if ((err = uiomove(&fniio, sizeof(fniio), uio)) != 0)
return (err); return (err);

View File

@ -519,9 +519,12 @@ fuse_vfsop_unmount(struct mount *mp, int mntflags)
return 0; return 0;
} }
SDT_PROBE_DEFINE1(fusefs, , vfsops, invalidate_without_export,
"struct mount*");
static int static int
fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) 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; uint64_t nodeid = ino;
struct thread *td = curthread; struct thread *td = curthread;
struct fuse_dispatcher fdi; struct fuse_dispatcher fdi;
@ -532,6 +535,15 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
enum vtype vtyp; enum vtype vtyp;
int error; 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); error = fuse_internal_get_cached_vnode(mp, ino, flags, vpp);
if (error || *vpp != NULL) if (error || *vpp != NULL)
return error; return error;

View File

@ -50,11 +50,6 @@ using namespace testing;
class Notify: public FuseTest { class Notify: public FuseTest {
public: public:
virtual void SetUp() {
m_init_flags = FUSE_EXPORT_SUPPORT;
FuseTest::SetUp();
}
void expect_lookup(uint64_t parent, const char *relpath, uint64_t ino, void expect_lookup(uint64_t parent, const char *relpath, uint64_t ino,
off_t size, Sequence &seq) off_t size, Sequence &seq)
{ {