FUSE: Respect userspace FS "do-not-cache" of path components
The FUSE protocol demands that kernel implementations cache user filesystem path components (lookup/cnp data) for a maximum period of time in the range of [0, ULONG_MAX] seconds. In practice, typical requests are for 0, 1, or 10 seconds; or "a long time" to represent indefinite caching. Historically, FreeBSD FUSE has ignored this client directive entirely. This works fine for local-only filesystems, but causes consistency issues with multi-writer network filesystems. For now, respect 0 second cache TTLs and do not cache such metadata. Non-zero metadata caching TTLs in the range [0.000000001, ULONG_MAX] seconds are still cached indefinitely, because it is unclear how a userspace filesystem could do anything sensible with those semantics even if implemented. Pass fuse_entry_out to fuse_vnode_get when available and only cache lookup if the user filesystem did not set a zero second TTL. PR: 230258 (inspired by; does not fix)
This commit is contained in:
parent
78a7722fbc
commit
09176f096b
@ -471,7 +471,7 @@ fuse_internal_newentry_core(struct vnode *dvp,
|
||||
if ((err = fuse_internal_checkentry(feo, vtyp))) {
|
||||
return err;
|
||||
}
|
||||
err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, vtyp);
|
||||
err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, vtyp);
|
||||
if (err) {
|
||||
fuse_internal_forget_send(mp, cnp->cn_thread, cnp->cn_cred,
|
||||
feo->nodeid, 1);
|
||||
|
@ -241,6 +241,7 @@ fuse_vnode_alloc(struct mount *mp,
|
||||
|
||||
int
|
||||
fuse_vnode_get(struct mount *mp,
|
||||
struct fuse_entry_out *feo,
|
||||
uint64_t nodeid,
|
||||
struct vnode *dvp,
|
||||
struct vnode **vpp,
|
||||
@ -261,7 +262,9 @@ fuse_vnode_get(struct mount *mp,
|
||||
MPASS(!(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.'));
|
||||
fuse_vnode_setparent(*vpp, dvp);
|
||||
}
|
||||
if (dvp != NULL && cnp != NULL && (cnp->cn_flags & MAKEENTRY) != 0) {
|
||||
if (dvp != NULL && cnp != NULL && (cnp->cn_flags & MAKEENTRY) != 0 &&
|
||||
feo != NULL &&
|
||||
(feo->entry_valid != 0 || feo->entry_valid_nsec != 0)) {
|
||||
ASSERT_VOP_LOCKED(*vpp, "fuse_vnode_get");
|
||||
ASSERT_VOP_LOCKED(dvp, "fuse_vnode_get");
|
||||
cache_enter(dvp, *vpp, cnp);
|
||||
|
@ -117,6 +117,7 @@ fuse_vnode_setparent(struct vnode *vp, struct vnode *dvp)
|
||||
void fuse_vnode_destroy(struct vnode *vp);
|
||||
|
||||
int fuse_vnode_get(struct mount *mp,
|
||||
struct fuse_entry_out *feo,
|
||||
uint64_t nodeid,
|
||||
struct vnode *dvp,
|
||||
struct vnode **vpp,
|
||||
|
@ -444,7 +444,8 @@ fuse_vfsop_root(struct mount *mp, int lkflags, struct vnode **vpp)
|
||||
if (err == 0)
|
||||
*vpp = data->vroot;
|
||||
} else {
|
||||
err = fuse_vnode_get(mp, FUSE_ROOT_ID, NULL, vpp, NULL, VDIR);
|
||||
err = fuse_vnode_get(mp, NULL, FUSE_ROOT_ID, NULL, vpp, NULL,
|
||||
VDIR);
|
||||
if (err == 0) {
|
||||
FUSE_LOCK();
|
||||
MPASS(data->vroot == NULL || data->vroot == *vpp);
|
||||
|
@ -384,7 +384,7 @@ fuse_vnop_create(struct vop_create_args *ap)
|
||||
if ((err = fuse_internal_checkentry(feo, VREG))) {
|
||||
goto out;
|
||||
}
|
||||
err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, VREG);
|
||||
err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, VREG);
|
||||
if (err) {
|
||||
struct fuse_release_in *fri;
|
||||
uint64_t nodeid = feo->nodeid;
|
||||
@ -857,8 +857,8 @@ calldaemon:
|
||||
vref(dvp);
|
||||
*vpp = dvp;
|
||||
} else {
|
||||
err = fuse_vnode_get(dvp->v_mount, nid, dvp,
|
||||
&vp, cnp, IFTOVT(fattr->mode));
|
||||
err = fuse_vnode_get(dvp->v_mount, feo, nid,
|
||||
dvp, &vp, cnp, IFTOVT(fattr->mode));
|
||||
if (err)
|
||||
goto out;
|
||||
*vpp = vp;
|
||||
@ -893,12 +893,8 @@ calldaemon:
|
||||
err = EISDIR;
|
||||
goto out;
|
||||
}
|
||||
err = fuse_vnode_get(vnode_mount(dvp),
|
||||
nid,
|
||||
dvp,
|
||||
&vp,
|
||||
cnp,
|
||||
IFTOVT(fattr->mode));
|
||||
err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
|
||||
&vp, cnp, IFTOVT(fattr->mode));
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
@ -936,12 +932,8 @@ calldaemon:
|
||||
}
|
||||
}
|
||||
VOP_UNLOCK(dvp, 0);
|
||||
err = fuse_vnode_get(vnode_mount(dvp),
|
||||
nid,
|
||||
NULL,
|
||||
&vp,
|
||||
cnp,
|
||||
IFTOVT(fattr->mode));
|
||||
err = fuse_vnode_get(vnode_mount(dvp), feo, nid, NULL,
|
||||
&vp, cnp, IFTOVT(fattr->mode));
|
||||
vfs_unbusy(mp);
|
||||
vn_lock(dvp, ltype | LK_RETRY);
|
||||
if ((dvp->v_iflag & VI_DOOMED) != 0) {
|
||||
@ -956,12 +948,8 @@ calldaemon:
|
||||
vref(dvp);
|
||||
*vpp = dvp;
|
||||
} else {
|
||||
err = fuse_vnode_get(vnode_mount(dvp),
|
||||
nid,
|
||||
dvp,
|
||||
&vp,
|
||||
cnp,
|
||||
IFTOVT(fattr->mode));
|
||||
err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp,
|
||||
&vp, cnp, IFTOVT(fattr->mode));
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user