git: 750d429a228f - main - vfs cache: further massage some commentary

From: Mateusz Guzik <mjg_at_FreeBSD.org>
Date: Wed, 08 Jul 2026 21:15:35 UTC
The branch main has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=750d429a228fb102d6e5d45bdc116489acbfff00

commit 750d429a228fb102d6e5d45bdc116489acbfff00
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2026-07-08 21:13:34 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2026-07-08 21:15:31 +0000

    vfs cache: further massage some commentary
---
 sys/kern/vfs_cache.c | 18 +++++++++++++-----
 1 file 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);