mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
Do not clear UN_ULOCK in certain case.
Our vput calls vm_object_deallocate() --> vm_object_terminate(). The vm_object_terminate() calls vn_lock(), since UN_LOCKED has been already cleared in union_unlock(). Then, union_lock locks upper vnode when UN_ULOCK is not set. The upper vnode is not unlocked when UN_KLOCK is set in union_unlock(), thus, union_lock tries to lock locked vnode and we get panic.
This commit is contained in:
parent
9ca8226735
commit
928e13b6a1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=25160
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
|
||||
* $Id: union_vnops.c,v 1.26 1997/04/21 12:40:42 kato Exp $
|
||||
* $Id: union_vnops.c,v 1.27 1997/04/21 15:32:24 kato Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -1492,6 +1492,7 @@ union_lock(ap)
|
||||
panic("union_link: upper vnode is locked, "
|
||||
"but UN_UNLOCK is not set.");
|
||||
#endif
|
||||
printf("union_lock: adjust un_flags\n");
|
||||
un->un_flags |= UN_ULOCK; /* Adjust -- dirty */
|
||||
} else {
|
||||
error = vn_lock(un->un_uppervp, flags, p);
|
||||
@ -1565,7 +1566,16 @@ union_unlock(ap)
|
||||
if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK)
|
||||
VOP_UNLOCK(un->un_uppervp, 0, p);
|
||||
|
||||
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
|
||||
if ((un->un_flags & UN_KLOCK) && (ap->a_vp->v_usecount == 1)) {
|
||||
/*
|
||||
* Do not clear UN_ULOCK here. Our vput will call
|
||||
* VOP_LOCK for vm related reason. If we clear UN_ULOCK,
|
||||
* VOP_LOCK will try to lock upper vnode, whic is not
|
||||
* unlocked.
|
||||
*/
|
||||
un->un_flags &= ~UN_KLOCK;
|
||||
} else
|
||||
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
|
||||
|
||||
if (un->un_flags & UN_WANT) {
|
||||
un->un_flags &= ~UN_WANT;
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
|
||||
* $Id: union_vnops.c,v 1.26 1997/04/21 12:40:42 kato Exp $
|
||||
* $Id: union_vnops.c,v 1.27 1997/04/21 15:32:24 kato Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -1492,6 +1492,7 @@ union_lock(ap)
|
||||
panic("union_link: upper vnode is locked, "
|
||||
"but UN_UNLOCK is not set.");
|
||||
#endif
|
||||
printf("union_lock: adjust un_flags\n");
|
||||
un->un_flags |= UN_ULOCK; /* Adjust -- dirty */
|
||||
} else {
|
||||
error = vn_lock(un->un_uppervp, flags, p);
|
||||
@ -1565,7 +1566,16 @@ union_unlock(ap)
|
||||
if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK)
|
||||
VOP_UNLOCK(un->un_uppervp, 0, p);
|
||||
|
||||
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
|
||||
if ((un->un_flags & UN_KLOCK) && (ap->a_vp->v_usecount == 1)) {
|
||||
/*
|
||||
* Do not clear UN_ULOCK here. Our vput will call
|
||||
* VOP_LOCK for vm related reason. If we clear UN_ULOCK,
|
||||
* VOP_LOCK will try to lock upper vnode, whic is not
|
||||
* unlocked.
|
||||
*/
|
||||
un->un_flags &= ~UN_KLOCK;
|
||||
} else
|
||||
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
|
||||
|
||||
if (un->un_flags & UN_WANT) {
|
||||
un->un_flags &= ~UN_WANT;
|
||||
|
Loading…
Reference in New Issue
Block a user