git: 7fd37611b92b - main - null_vptocnp(): busy nullfs mp instead of refing it
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 14 Jun 2022 07:33:22 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=7fd37611b92b5f365f33435bb725b335c2f10ba8 commit 7fd37611b92b5f365f33435bb725b335c2f10ba8 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2022-06-10 11:35:45 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2022-06-14 07:32:45 +0000 null_vptocnp(): busy nullfs mp instead of refing it null_nodeget() needs a valid mount point data, otherwise we might race and dereference NULL. Using MBF_NOWAIT makes non-forced unmount non-transparent for vn_fullpath() over nullfs, but we make no guarantee that fullpath calculation succeeds anyway. Reported and tested by: pho Reviewed by: jah Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D35477 --- sys/fs/nullfs/null_vnops.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index e3a320a22bfa..bb18bc8ee55f 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -989,9 +989,11 @@ null_vptocnp(struct vop_vptocnp_args *ap) locked = VOP_ISLOCKED(vp); lvp = NULLVPTOLOWERVP(vp); - vhold(lvp); mp = vp->v_mount; - vfs_ref(mp); + error = vfs_busy(mp, MBF_NOWAIT); + if (error != 0) + return (error); + vhold(lvp); VOP_UNLOCK(vp); /* vp is held by vn_vptocnp_locked that called us */ ldvp = lvp; vref(lvp); @@ -999,7 +1001,7 @@ null_vptocnp(struct vop_vptocnp_args *ap) vdrop(lvp); if (error != 0) { vn_lock(vp, locked | LK_RETRY); - vfs_rel(mp); + vfs_unbusy(mp); return (ENOENT); } @@ -1007,7 +1009,7 @@ null_vptocnp(struct vop_vptocnp_args *ap) if (error != 0) { vrele(ldvp); vn_lock(vp, locked | LK_RETRY); - vfs_rel(mp); + vfs_unbusy(mp); return (ENOENT); } error = null_nodeget(mp, ldvp, dvp); @@ -1018,7 +1020,7 @@ null_vptocnp(struct vop_vptocnp_args *ap) VOP_UNLOCK(*dvp); /* keep reference on *dvp */ } vn_lock(vp, locked | LK_RETRY); - vfs_rel(mp); + vfs_unbusy(mp); return (error); }