In nfs_upgrade_vnlock(), assert that the vnode is locked. It is for all
pathes, as far as I see and testing seems to confirm it. Comparision of old_lock with LK_SHARED make sense only if vnode is locked by current thread. When downgrading, pass LK_RETRY to the vn_lock(), since otherwise vn_lock() unlocks the doomed vnode, causing extra unlock. Reported and tested by: pho Approved by: re (rwatson) MFC after: 3 weeks
This commit is contained in:
parent
aabd624cf4
commit
48bd6d4a49
@ -409,28 +409,25 @@ int
|
||||
nfs_upgrade_vnlock(struct vnode *vp)
|
||||
{
|
||||
int old_lock;
|
||||
|
||||
if ((old_lock = VOP_ISLOCKED(vp)) != LK_EXCLUSIVE) {
|
||||
if (old_lock == LK_SHARED) {
|
||||
/* Upgrade to exclusive lock, this might block */
|
||||
vn_lock(vp, LK_UPGRADE | LK_RETRY);
|
||||
} else {
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
}
|
||||
|
||||
ASSERT_VOP_LOCKED(vp, "nfs_upgrade_vnlock");
|
||||
old_lock = VOP_ISLOCKED(vp);
|
||||
if (old_lock != LK_EXCLUSIVE) {
|
||||
KASSERT(old_lock == LK_SHARED,
|
||||
("nfs_upgrade_vnlock: wrong old_lock %d", old_lock));
|
||||
/* Upgrade to exclusive lock, this might block */
|
||||
vn_lock(vp, LK_UPGRADE | LK_RETRY);
|
||||
}
|
||||
return old_lock;
|
||||
return (old_lock);
|
||||
}
|
||||
|
||||
void
|
||||
nfs_downgrade_vnlock(struct vnode *vp, int old_lock)
|
||||
{
|
||||
if (old_lock != LK_EXCLUSIVE) {
|
||||
if (old_lock == LK_SHARED) {
|
||||
/* Downgrade from exclusive lock, this might block */
|
||||
vn_lock(vp, LK_DOWNGRADE);
|
||||
} else {
|
||||
VOP_UNLOCK(vp, 0);
|
||||
}
|
||||
KASSERT(old_lock == LK_SHARED, ("wrong old_lock %d", old_lock));
|
||||
/* Downgrade from exclusive lock. */
|
||||
vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user