git: a8e92198f854 - main - devfs: unlock the directory vnode around the call to dev_clone handler
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Feb 2026 19:51:20 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=a8e92198f854c2766eedec5a2ea3cc23c64d7b12
commit a8e92198f854c2766eedec5a2ea3cc23c64d7b12
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-26 01:49:32 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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);