diff options
| author | Mateusz Guzik <mjg@FreeBSD.org> | 2026-07-08 21:13:34 +0000 |
|---|---|---|
| committer | Mateusz Guzik <mjg@FreeBSD.org> | 2026-07-08 21:15:31 +0000 |
| commit | 750d429a228fb102d6e5d45bdc116489acbfff00 (patch) | |
| tree | 75e78fbea927e709e16e03a4de8e6bb52617a13a | |
| parent | 665bb2d9a440d33e2ec2f9151e45b8cda93433ae (diff) | |
vfs cache: further massage some commentary
| -rw-r--r-- | sys/kern/vfs_cache.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 66210bf58a7c..9e1c9cb757b5 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -6349,7 +6349,7 @@ cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl) * Note: all VOP_FPLOOKUP_VEXEC routines have a comment referencing this one. * * Filesystems can opt in by setting the MNTK_FPLOOKUP flag and meeting criteria - * outlined at the end. + * outlined at the end of this comment. * * Traversing from one vnode to another requires atomicity with regard to * permissions, mount points and of course their relative placement (if you are @@ -6370,6 +6370,13 @@ cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl) * See places which issue vn_seqc_write_begin()/vn_seqc_write_end() for * operations affected. * + * Note: regardless of locked or unlocked operation atomicity of traversal only + * covers the immediate move from one vnode to the next. For example, suppose you + * are looking up "foo/level2/level3" and are racing against rename("foo", bar"). + * If the vnode for "level2" was found and locked prior to the rename call locking + * "foo", then by the time "level3" is locked the true path might happen to be + * "bar/level2/level3". + * * Suppose the variable "cnp" contains lookup metadata (the path etc.), then * locked lookup conceptually looks like this: * @@ -6378,16 +6385,16 @@ cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl) * for (;;) { * // permission check * if (!canlookup(dvp, cnp)) - * abort(); + * fail(); * // look for the target name inside dvp * tvp = findnext(dvp, cnp); * vn_lock(tvp); * // tvp is still guaranteed to be inside of dvp because of the lock on dvp * vn_unlock(dvp); - * // dvp is unlocked. its state is now arbitrary, but that's fine as we + * // dvp is unlocked and its state is now arbitrary, but that's fine as we * // made the jump while everything relevant was correct, continue with tvp * // as the directory to look up names in - * tvp = dvp; + * dvp = tvp; * if (last) * break; * // if not last loop back and continue until done @@ -6395,7 +6402,8 @@ cache_fplookup_impl(struct vnode *dvp, struct cache_fpl *fpl) * vget(tvp); * return (tvp); * - * Lockless lookup replaces locking with sequence counter checks: + * Lockless lookup replaces locking with sequence counter checks. If any of + * them fail, it falls back to locked traversal. * * vfs_smr_enter(); * dvp_seqc = seqc_read_any(dvp); |
