git: fffd409a29ce - stable/15 - devfs: unlock the directory vnode around the call to dev_clone handler

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 09 Feb 2026 00:52:21 UTC
The branch stable/15 has been updated by kib:

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

commit fffd409a29ce4966f2cca620aedc9f0eb1df9862
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-26 01:49:32 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-02-09 00:51:57 +0000

    devfs: unlock the directory vnode around the call to dev_clone handler
    
    (cherry picked from commit a8e92198f854c2766eedec5a2ea3cc23c64d7b12)
---
 sys/fs/devfs/devfs_vnops.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 880756264b0f..8c188e768de8 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -367,6 +367,9 @@ devfs_populate_vp(struct vnode *vp)
 
 	ASSERT_VOP_LOCKED(vp, "devfs_populate_vp");
 
+	if (VN_IS_DOOMED(vp))
+		return (ENOENT);
+
 	dmp = VFSTODEVFS(vp->v_mount);
 	if (!devfs_populate_needed(dmp)) {
 		sx_xlock(&dmp->dm_lock);
@@ -1128,8 +1131,25 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)
 		cdev = NULL;
 		DEVFS_DMP_HOLD(dmp);
 		sx_xunlock(&dmp->dm_lock);
+		dvplocked = VOP_ISLOCKED(dvp);
+
+		/*
+		 * Invoke the dev_clone handler.  Unlock dvp around it
+		 * to simplify the cloner operations.
+		 *
+		 * If dvp is reclaimed while we unlocked it, we return
+		 * with ENOENT by some of the paths below.  If cloner
+		 * returned cdev, then devfs_populate_vp() notes the
+		 * reclamation.  Otherwise, note that either our devfs
+		 * mount is being unmounted, then DEVFS_DMP_DROP()
+		 * returns true, and we return ENOENT this way.  Or,
+		 * because de == NULL, the check for it after the loop
+		 * returns ENOENT.
+		 */
+		VOP_UNLOCK(dvp);
 		EVENTHANDLER_INVOKE(dev_clone,
 		    td->td_ucred, pname, strlen(pname), &cdev);
+		vn_lock(dvp, dvplocked | LK_RETRY);
 
 		if (cdev == NULL)
 			sx_xlock(&dmp->dm_lock);