fusefs: implement entry cache timeouts
Follow-up to r346046. These two commits implement fuse cache timeouts for both entries and attributes. They also remove the vfs.fusefs.lookup_cache enable sysctl, which is no longer needed now that cache timeouts are honored. PR: 235773 Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
3f2c630c74
commit
ccb75e4939
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=346060
@ -68,8 +68,6 @@
|
|||||||
#include "fuse_ipc.h"
|
#include "fuse_ipc.h"
|
||||||
#include "fuse_node.h"
|
#include "fuse_node.h"
|
||||||
|
|
||||||
extern int fuse_lookup_cache_expire;
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
vfs_isrdonly(struct mount *mp)
|
vfs_isrdonly(struct mount *mp)
|
||||||
{
|
{
|
||||||
|
@ -291,24 +291,21 @@ fuse_vnode_get(struct mount *mp,
|
|||||||
if (dvp != NULL && cnp != NULL && (cnp->cn_flags & MAKEENTRY) != 0 &&
|
if (dvp != NULL && cnp != NULL && (cnp->cn_flags & MAKEENTRY) != 0 &&
|
||||||
feo != NULL &&
|
feo != NULL &&
|
||||||
(feo->entry_valid != 0 || feo->entry_valid_nsec != 0)) {
|
(feo->entry_valid != 0 || feo->entry_valid_nsec != 0)) {
|
||||||
|
struct timespec duration, now, timeout;
|
||||||
|
|
||||||
ASSERT_VOP_LOCKED(*vpp, "fuse_vnode_get");
|
ASSERT_VOP_LOCKED(*vpp, "fuse_vnode_get");
|
||||||
ASSERT_VOP_LOCKED(dvp, "fuse_vnode_get");
|
ASSERT_VOP_LOCKED(dvp, "fuse_vnode_get");
|
||||||
if (fuse_lookup_cache_expire) {
|
|
||||||
struct timespec duration, now, timeout;
|
|
||||||
|
|
||||||
getnanouptime(&now);
|
getnanouptime(&now);
|
||||||
if (feo->entry_valid >= INT_MAX ||
|
if (feo->entry_valid >= INT_MAX ||
|
||||||
feo->entry_valid + now.tv_sec + 2 >= INT_MAX) {
|
feo->entry_valid + now.tv_sec + 2 >= INT_MAX) {
|
||||||
timeout.tv_sec = INT_MAX;
|
timeout.tv_sec = INT_MAX;
|
||||||
} else {
|
|
||||||
duration.tv_sec = feo->entry_valid;
|
|
||||||
duration.tv_nsec = feo->entry_valid_nsec;
|
|
||||||
timespecadd(&duration, &now, &timeout);
|
|
||||||
}
|
|
||||||
cache_enter_time(dvp, *vpp, cnp, &timeout, NULL);
|
|
||||||
} else {
|
} else {
|
||||||
cache_enter(dvp, *vpp, cnp);
|
duration.tv_sec = feo->entry_valid;
|
||||||
|
duration.tv_nsec = feo->entry_valid_nsec;
|
||||||
|
timespecadd(&duration, &now, &timeout);
|
||||||
}
|
}
|
||||||
|
cache_enter_time(dvp, *vpp, cnp, &timeout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -195,12 +195,6 @@ static u_long fuse_lookup_cache_misses = 0;
|
|||||||
SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_misses, CTLFLAG_RD,
|
SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_misses, CTLFLAG_RD,
|
||||||
&fuse_lookup_cache_misses, 0, "number of cache misses in lookup");
|
&fuse_lookup_cache_misses, 0, "number of cache misses in lookup");
|
||||||
|
|
||||||
int fuse_lookup_cache_expire = 0;
|
|
||||||
|
|
||||||
SYSCTL_INT(_vfs_fusefs, OID_AUTO, lookup_cache_expire, CTLFLAG_RW,
|
|
||||||
&fuse_lookup_cache_expire, 0,
|
|
||||||
"if non-zero, expire fuse lookup cache entries at the proper time");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: This feature is highly experimental and can bring to instabilities,
|
* XXX: This feature is highly experimental and can bring to instabilities,
|
||||||
* needs revisiting before to be enabled by default.
|
* needs revisiting before to be enabled by default.
|
||||||
@ -681,6 +675,8 @@ fuse_vnop_link(struct vop_link_args *ap)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDT_PROBE_DEFINE3(fuse, , vnops, cache_lookup,
|
||||||
|
"int", "struct timespec*", "struct timespec*");
|
||||||
/*
|
/*
|
||||||
struct vnop_lookup_args {
|
struct vnop_lookup_args {
|
||||||
struct vnodeop_desc *a_desc;
|
struct vnodeop_desc *a_desc;
|
||||||
@ -750,21 +746,26 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
|
|||||||
fdisp_init(&fdi, 0);
|
fdisp_init(&fdi, 0);
|
||||||
op = FUSE_GETATTR;
|
op = FUSE_GETATTR;
|
||||||
goto calldaemon;
|
goto calldaemon;
|
||||||
} else if (fuse_lookup_cache_expire) {
|
} else {
|
||||||
struct timespec now, timeout;
|
struct timespec now, timeout;
|
||||||
|
|
||||||
err = cache_lookup(dvp, vpp, cnp, &timeout, NULL);
|
err = cache_lookup(dvp, vpp, cnp, &timeout, NULL);
|
||||||
|
getnanouptime(&now);
|
||||||
|
SDT_PROBE3(fuse, , vnops, cache_lookup, err, &timeout, &now);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
|
||||||
case -1: /* positive match */
|
case -1: /* positive match */
|
||||||
getnanouptime(&now);
|
if (timespeccmp(&timeout, &now, >)) {
|
||||||
if (timespeccmp(&timeout, &now, <=)) {
|
|
||||||
atomic_add_acq_long(&fuse_lookup_cache_hits, 1);
|
atomic_add_acq_long(&fuse_lookup_cache_hits, 1);
|
||||||
} else {
|
} else {
|
||||||
/* Cache timeout */
|
/* Cache timeout */
|
||||||
atomic_add_acq_long(&fuse_lookup_cache_misses,
|
atomic_add_acq_long(&fuse_lookup_cache_misses,
|
||||||
1);
|
1);
|
||||||
cache_purge(*vpp);
|
fuse_internal_vnode_disappear(*vpp);
|
||||||
|
if (dvp != *vpp)
|
||||||
|
vput(*vpp);
|
||||||
|
else
|
||||||
|
vrele(*vpp);
|
||||||
|
*vpp = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -775,34 +776,15 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
|
|||||||
|
|
||||||
case ENOENT: /* negative match */
|
case ENOENT: /* negative match */
|
||||||
getnanouptime(&now);
|
getnanouptime(&now);
|
||||||
if (timespeccmp(&timeout, &now, >)) {
|
if (timespeccmp(&timeout, &now, <=)) {
|
||||||
/* Cache timeout */
|
/* Cache timeout */
|
||||||
printf("Purging vnode %p name=%s\n", *vpp,
|
cache_purge_negative(dvp);
|
||||||
cnp->cn_nameptr);
|
|
||||||
fuse_internal_vnode_disappear(*vpp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
err = cache_lookup(dvp, vpp, cnp, NULL, NULL);
|
|
||||||
switch (err) {
|
|
||||||
|
|
||||||
case -1: /* positive match */
|
|
||||||
atomic_add_acq_long(&fuse_lookup_cache_hits, 1);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case 0: /* no match in cache */
|
|
||||||
atomic_add_acq_long(&fuse_lookup_cache_misses, 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENOENT: /* negative match */
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
nid = VTOI(dvp);
|
nid = VTOI(dvp);
|
||||||
fdisp_init(&fdi, cnp->cn_namelen + 1);
|
fdisp_init(&fdi, cnp->cn_namelen + 1);
|
||||||
@ -817,13 +799,15 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
|
|||||||
}
|
}
|
||||||
lookup_err = fdisp_wait_answ(&fdi);
|
lookup_err = fdisp_wait_answ(&fdi);
|
||||||
|
|
||||||
if ((op == FUSE_LOOKUP) && !lookup_err) { /* lookup call succeeded */
|
if ((op == FUSE_LOOKUP) && !lookup_err) {
|
||||||
|
/* lookup call succeeded */
|
||||||
nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
|
nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
|
||||||
if (!nid) {
|
if (!nid) {
|
||||||
/*
|
/*
|
||||||
* zero nodeid is the same as "not found",
|
* zero nodeid is the same as "not found",
|
||||||
* but it's also cacheable (which we keep
|
* but it's also cacheable (which we keep
|
||||||
* keep on doing not as of writing this)
|
* keep on doing not as of writing this)
|
||||||
|
* See PR 236226
|
||||||
*/
|
*/
|
||||||
fdi.answ_stat = ENOENT;
|
fdi.answ_stat = ENOENT;
|
||||||
lookup_err = ENOENT;
|
lookup_err = ENOENT;
|
||||||
|
@ -211,8 +211,7 @@ TEST_F(Lookup, entry_cache_negative_timeout)
|
|||||||
* If lookup returns a finite but non-zero entry cache timeout, then we should
|
* If lookup returns a finite but non-zero entry cache timeout, then we should
|
||||||
* discard the cached inode and requery the daemon
|
* discard the cached inode and requery the daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235773 */
|
TEST_F(Lookup, entry_cache_timeout)
|
||||||
TEST_F(Lookup, DISABLED_entry_cache_timeout)
|
|
||||||
{
|
{
|
||||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||||
const char RELPATH[] = "some_file.txt";
|
const char RELPATH[] = "some_file.txt";
|
||||||
|
Loading…
Reference in New Issue
Block a user