The branch main has been updated by kib:

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

commit a8e92198f854c2766eedec5a2ea3cc23c64d7b12
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-01-26 01:49:32 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-02-02 19:48:25 +0000

    devfs: unlock the directory vnode around the call to dev_clone handler
    
    The lock around dev_clone is unfortunate because cloner might need to
    take its own locks that establish the order with devfs vnodes, and then
    transiently participates in further VFS locks order.  For instance, this
    way the proctree_lock or allproc_lock become involved.
    
    Unlock dvp, we can unwind if the vnode become doomed while cloner was
    called.
    
    Reported and tested by: pho
    Reviewed by:    kevans, markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D55028
---
 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 323f1e0fa961..d594b1584757 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);

Reply via email to