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
This commit is contained in:
parent
21ef48af5c
commit
a18c403fbd
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user