git: 26b964875014 - main - vfs: more informative panic for missing fplookup ops

From: Mateusz Guzik <mjg_at_FreeBSD.org>
Date: Fri, 07 Apr 2023 20:41:55 UTC
The branch main has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=26b964875014a0d61f765428b1cb2768917f693c

commit 26b964875014a0d61f765428b1cb2768917f693c
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2023-04-07 19:48:33 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2023-04-07 20:39:06 +0000

    vfs: more informative panic for missing fplookup ops
---
 sys/kern/vfs_cache.c | 40 ++++++++++++++++++++++++++++++++++++++--
 sys/kern/vfs_subr.c  |  5 +----
 sys/sys/vnode.h      |  6 ++++++
 3 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 2ffa48f12299..294f7740dacf 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -3956,6 +3956,20 @@ static int cache_fast_lookup = 1;
 
 #define CACHE_FPL_FAILED	-2020
 
+static int
+cache_vop_bad_vexec(struct vop_fplookup_vexec_args *v)
+{
+	vn_printf(v->a_vp, "no proper vop_fplookup_vexec\n");
+	panic("no proper vop_fplookup_vexec");
+}
+
+static int
+cache_vop_bad_symlink(struct vop_fplookup_symlink_args *v)
+{
+	vn_printf(v->a_vp, "no proper vop_fplookup_symlink\n");
+	panic("no proper vop_fplookup_symlink");
+}
+
 void
 cache_vop_vector_register(struct vop_vector *v)
 {
@@ -3974,8 +3988,8 @@ cache_vop_vector_register(struct vop_vector *v)
 	}
 
 	if (ops == 0) {
-		v->vop_fplookup_vexec = VOP_PANIC;
-		v->vop_fplookup_symlink = VOP_PANIC;
+		v->vop_fplookup_vexec = cache_vop_bad_vexec;
+		v->vop_fplookup_symlink = cache_vop_bad_symlink;
 		return;
 	}
 
@@ -3990,6 +4004,28 @@ cache_vop_vector_register(struct vop_vector *v)
 	panic("bad vop vector %p", v);
 }
 
+#ifdef INVARIANTS
+void
+cache_validate_vop_vector(struct mount *mp, struct vop_vector *vops)
+{
+	if (mp == NULL)
+		return;
+
+	if ((mp->mnt_kern_flag & MNTK_FPLOOKUP) == 0)
+		return;
+
+	if (vops->vop_fplookup_vexec == NULL ||
+	    vops->vop_fplookup_vexec == cache_vop_bad_vexec)
+		panic("bad vop_fplookup_vexec on vector %p for filesystem %s",
+		    vops, mp->mnt_vfc->vfc_name);
+
+	if (vops->vop_fplookup_symlink == NULL ||
+	    vops->vop_fplookup_symlink == cache_vop_bad_symlink)
+		panic("bad vop_fplookup_symlink on vector %p for filesystem %s",
+		    vops, mp->mnt_vfc->vfc_name);
+}
+#endif
+
 void
 cache_fast_lookup_enabled_recalc(void)
 {
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 96adc6ff3493..1da299e93eea 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1800,10 +1800,7 @@ getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
 
 	KASSERT(vops->registered,
 	    ("%s: not registered vector op %p\n", __func__, vops));
-	if (mp != NULL && (mp->mnt_kern_flag & MNTK_FPLOOKUP) != 0) {
-		MPASS(vops->vop_fplookup_vexec != VOP_PANIC);
-		MPASS(vops->vop_fplookup_symlink != VOP_PANIC);
-	}
+	cache_validate_vop_vector(mp, vops);
 
 	td = curthread;
 	if (td->td_vp_reserved != NULL) {
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 2a62c6d1b659..74514654713a 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -654,6 +654,7 @@ void	cache_vop_vector_register(struct vop_vector *);
 #ifdef INVARIANTS
 void	cache_validate(struct vnode *dvp, struct vnode *vp,
 	    struct componentname *cnp);
+void	cache_validate_vop_vector(struct mount *mp, struct vop_vector *vops);
 void	cache_assert_no_entries(struct vnode *vp);
 #else
 static inline void
@@ -661,6 +662,11 @@ cache_validate(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
 {
 }
 
+static inline void
+cache_validate_vop_vector(struct mount *mp, struct vop_vector *vops)
+{
+}
+
 static inline void
 cache_assert_no_entries(struct vnode *vp)
 {