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:
Konstantin Belousov 2009-08-14 10:59:17 +00:00
parent aabd624cf4
commit 48bd6d4a49

View File

@ -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);
}
}