aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/fuse/fuse_internal.c
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2019-06-27 20:18:12 +0000
committerAlan Somers <asomers@FreeBSD.org>2019-06-27 20:18:12 +0000
commit435ecf40bbf56a6554ff9f9b51b1a783dffa2f42 (patch)
treed6ff33d827db666a4bb3fd6281382d14a7cee9c9 /sys/fs/fuse/fuse_internal.c
parent38c8634635b765097cc7140c66f46958b6108a30 (diff)
downloadsrc-435ecf40bbf56a6554ff9f9b51b1a783dffa2f42.tar.gz
src-435ecf40bbf56a6554ff9f9b51b1a783dffa2f42.zip
fusefs: recycle vnodes after their last unlink
Previously fusefs would never recycle vnodes. After VOP_INACTIVE, they'd linger around until unmount or the vnlru reclaimed them. This commit essentially actives and inlines the old reclaim_revoked sysctl, and fixes some issues dealing with the attribute cache and multiply linked files. Sponsored by: The FreeBSD Foundation
Notes
Notes: svn path=/projects/fuse2/; revision=349468
Diffstat (limited to 'sys/fs/fuse/fuse_internal.c')
-rw-r--r--sys/fs/fuse/fuse_internal.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c
index 19dab451e529..91711f35238f 100644
--- a/sys/fs/fuse/fuse_internal.c
+++ b/sys/fs/fuse/fuse_internal.c
@@ -657,6 +657,7 @@ fuse_internal_remove(struct vnode *dvp,
enum fuse_opcode op)
{
struct fuse_dispatcher fdi;
+ nlink_t nlink;
int err = 0;
fdisp_init(&fdi, cnp->cn_namelen + 1);
@@ -667,6 +668,35 @@ fuse_internal_remove(struct vnode *dvp,
err = fdisp_wait_answ(&fdi);
fdisp_destroy(&fdi);
+
+ if (err)
+ return (err);
+
+ /*
+ * Access the cached nlink even if the attr cached has expired. If
+ * it's inaccurate, the worst that will happen is:
+ * 1) We'll recycle the vnode even though the file has another link we
+ * don't know about, costing a bit of cpu time, or
+ * 2) We won't recycle the vnode even though all of its links are gone.
+ * It will linger around until vnlru reclaims it, costing a bit of
+ * temporary memory.
+ */
+ nlink = VTOFUD(vp)->cached_attrs.va_nlink--;
+
+ /*
+ * Purge the parent's attribute cache because the daemon
+ * should've updated its mtime and ctime.
+ */
+ fuse_vnode_clear_attr_cache(dvp);
+
+ /* NB: nlink could be zero if it was never cached */
+ if (nlink <= 1 || vnode_vtype(vp) == VDIR) {
+ fuse_internal_vnode_disappear(vp);
+ } else {
+ cache_purge(vp);
+ fuse_vnode_update(vp, FN_CTIMECHANGE);
+ }
+
return err;
}
@@ -894,8 +924,6 @@ fuse_internal_vnode_disappear(struct vnode *vp)
ASSERT_VOP_ELOCKED(vp, "fuse_internal_vnode_disappear");
fvdat->flag |= FN_REVOKED;
- bintime_clear(&fvdat->attr_cache_timeout);
- bintime_clear(&fvdat->entry_cache_timeout);
cache_purge(vp);
}