diff options
author | Alan Somers <asomers@FreeBSD.org> | 2019-06-27 20:18:12 +0000 |
---|---|---|
committer | Alan Somers <asomers@FreeBSD.org> | 2019-06-27 20:18:12 +0000 |
commit | 435ecf40bbf56a6554ff9f9b51b1a783dffa2f42 (patch) | |
tree | d6ff33d827db666a4bb3fd6281382d14a7cee9c9 /sys/fs/fuse/fuse_internal.c | |
parent | 38c8634635b765097cc7140c66f46958b6108a30 (diff) | |
download | src-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.c | 32 |
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); } |