git: a18c403fbddb - main - unionfs: remove LK_UPGRADE if falling back to the standard lock
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 18 Apr 2023 01:35:41 UTC
The branch main has been updated by jah: URL: https://cgit.FreeBSD.org/src/commit/?id=a18c403fbddb0fa9650f133a026f40ad33751134 commit a18c403fbddb0fa9650f133a026f40ad33751134 Author: Jason A. Harmening <jah@FreeBSD.org> AuthorDate: 2023-01-16 21:46:59 +0000 Commit: Jason A. Harmening <jah@FreeBSD.org> CommitDate: 2023-04-18 01:31:40 +0000 unionfs: remove LK_UPGRADE if falling back to the standard lock The LK_UPGRADE operation may have temporarily dropped the upper or lower vnode's lock. If the unionfs vnode was reclaimed during that window, its lock field will be reset to no longer point at the upper/lower vnode lock, so the lock operation will use the standard lock stored in v_lock. Remove LK_UPGRADE from the flags in this case to avoid a lockmgr assertion, as this lock has not been previously owned by the calling thread. Reported by: pho Tested by: pho Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D39272 --- sys/fs/unionfs/union_vnops.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 04d788959892..f78e653280a4 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -2010,7 +2010,7 @@ unionfs_lock(struct vop_lock1_args *ap) vdrop(lvp); if (uhold != 0) vdrop(uvp); - return (vop_stdlock(ap)); + goto unionfs_lock_fallback; } } @@ -2043,7 +2043,7 @@ unionfs_lock(struct vop_lock1_args *ap) VOP_UNLOCK(lvp); vdrop(lvp); } - return (vop_stdlock(ap)); + goto unionfs_lock_fallback; } if (error != 0 && lvp != NULLVP) { /* rollback */ @@ -2065,6 +2065,22 @@ unionfs_lock(struct vop_lock1_args *ap) unionfs_lock_null_vnode: ap->a_flags |= LK_INTERLOCK; return (vop_stdlock(ap)); + +unionfs_lock_fallback: + /* + * If we reach this point, we've discovered the unionfs vnode + * has been reclaimed while the upper/lower vnode locks were + * temporarily dropped. Such temporary droppage may happen + * during the course of an LK_UPGRADE operation itself, and in + * that case LK_UPGRADE must be cleared as the unionfs vnode's + * lock has been reset to point to the standard v_lock field, + * which has not previously been held. + */ + if (flags & LK_UPGRADE) { + ap->a_flags &= ~LK_TYPE_MASK; + ap->a_flags |= LK_EXCLUSIVE; + } + return (vop_stdlock(ap)); } static int