git: 2d21dbaaaf75 - main - fix p9fs_vget_common() panics
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 04 Aug 2026 16:23:42 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=2d21dbaaaf75558b42a000561eb6224b6c1c0615
commit 2d21dbaaaf75558b42a000561eb6224b6c1c0615
Author: Nimish Jain <njain15@protonmail.com>
AuthorDate: 2026-08-03 23:08:31 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-08-04 16:00:48 +0000
fix p9fs_vget_common() panics
This addresses a race when two vnodes attempt to call vfs_hash_insert(),
but only one succeeds. Also, in case of an error from
p9fs_reload_stats_dotl(), it marks the vnode for deletion.
Reviewed by: kib
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D58632
---
sys/fs/p9fs/p9fs_vfsops.c | 56 +++++++++++++----------------------------------
sys/fs/p9fs/p9fs_vnops.c | 3 ---
2 files changed, 15 insertions(+), 44 deletions(-)
diff --git a/sys/fs/p9fs/p9fs_vfsops.c b/sys/fs/p9fs/p9fs_vfsops.c
index fe8c1b5ded31..7a0859806b35 100644
--- a/sys/fs/p9fs/p9fs_vfsops.c
+++ b/sys/fs/p9fs/p9fs_vfsops.c
@@ -263,7 +263,7 @@ p9fs_vget_common(struct mount *mp, struct p9fs_node *np, int flags,
struct p9fs_node *node;
struct thread *td;
uint32_t hash;
- int error, error_reload = 0;
+ int error;
struct p9fs_inode *inode;
td = curthread;
@@ -352,57 +352,31 @@ p9fs_vget_common(struct mount *mp, struct p9fs_node *np, int flags,
if (vp->v_type != VFIFO)
VN_LOCK_ASHARE(vp);
error = insmntque(vp, mp);
- if (error != 0) {
- /*
- * vput(vp) is already called from insmntque_stddtr().
- * Just goto 'out' to dispose the node.
- */
- goto out;
- }
+ if (error != 0)
+ return (error);
/* Init the vnode with the disk info*/
error = p9fs_reload_stats_dotl(vp, curthread->td_ucred);
if (error != 0) {
- error_reload = 1;
- goto out;
+ P9FS_NODE_SETF(np, P9FS_NODE_DELETED);
+ vgone(vp);
+ vput(vp);
+ return (error);
}
error = vfs_hash_insert(vp, hash, flags, td, vpp,
p9fs_node_cmp, &fid->qid);
- if (error != 0) {
- goto out;
- }
+ if (error != 0 || *vpp != NULL)
+ return (error);
- if (*vpp == NULL) {
- P9FS_LOCK(vses);
- STAILQ_INSERT_TAIL(&vses->virt_node_list, np, p9fs_node_next);
- P9FS_NODE_SETF(np, P9FS_NODE_IN_SESSION);
- P9FS_UNLOCK(vses);
- vn_set_state(vp, VSTATE_CONSTRUCTED);
- *vpp = vp;
- } else {
- /*
- * Returning matching vp found in hashlist.
- * So cleanup the np allocated above in this context.
- */
- if (!IS_ROOT(np)) {
- p9fs_destroy_node(&np);
- }
- }
+ P9FS_LOCK(vses);
+ STAILQ_INSERT_TAIL(&vses->virt_node_list, np, p9fs_node_next);
+ P9FS_NODE_SETF(np, P9FS_NODE_IN_SESSION);
+ P9FS_UNLOCK(vses);
+ vn_set_state(vp, VSTATE_CONSTRUCTED);
+ *vpp = vp;
return (0);
-out:
- /* Something went wrong, dispose the node */
- if (!IS_ROOT(np)) {
- p9fs_destroy_node(&np);
- }
-
- if (error_reload) {
- vput(vp);
- }
-
- *vpp = NULL;
- return (error);
}
/* Main mount function for 9pfs */
diff --git a/sys/fs/p9fs/p9fs_vnops.c b/sys/fs/p9fs/p9fs_vnops.c
index 2519e5cd050a..de2ffa3eb011 100644
--- a/sys/fs/p9fs/p9fs_vnops.c
+++ b/sys/fs/p9fs/p9fs_vnops.c
@@ -115,9 +115,6 @@ p9fs_cleanup(struct p9fs_node *np)
if ((np->flags & P9FS_NODE_IN_SESSION) != 0) {
P9FS_NODE_CLRF(np, P9FS_NODE_IN_SESSION);
STAILQ_REMOVE(&vses->virt_node_list, np, p9fs_node, p9fs_node_next);
- } else {
- P9FS_UNLOCK(vses);
- return;
}
P9FS_UNLOCK(vses);