When the MNTK_EXTENDED_SHARED mount option was added, some filesystems were

changed to defer the setting of VN_LOCK_ASHARE() (which clears LK_NOSHARE
in the vnode lock's flags) until after they had determined if the vnode was
a FIFO.  This occurs after the vnode has been inserted a VFS hash or some
similar table, so it is possible for another thread to find this vnode via
vget() on an i-node number and block on the vnode lock.  If the lockmgr
interlock (vnode interlock for vnode locks) is not held when clearing the
LK_NOSHARE flag, then the lk_flags field can be clobbered.  As a result
the thread blocked on the vnode lock may never get woken up.  Fix this by
holding the vnode interlock while modifying the lock flags in this case.

MFC after:	3 days
This commit is contained in:
John Baldwin 2010-07-16 19:20:20 +00:00
parent 12c5cab23e
commit dbfcf8cfea
4 changed files with 12 additions and 2 deletions

View File

@ -566,8 +566,11 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz)
}
break;
}
if (vp->v_type != VFIFO)
if (vp->v_type != VFIFO) {
VI_LOCK(vp);
VN_LOCK_ASHARE(vp);
VI_UNLOCK(vp);
}
mutex_enter(&zfsvfs->z_znodes_lock);
list_insert_tail(&zfsvfs->z_all_znodes, zp);

View File

@ -814,7 +814,9 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
vp->v_op = &cd9660_fifoops;
break;
default:
VI_LOCK(vp);
VN_LOCK_ASHARE(vp);
VI_UNLOCK(vp);
break;
}

View File

@ -710,8 +710,11 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
break;
}
if (vp->v_type != VFIFO)
if (vp->v_type != VFIFO) {
VI_LOCK(vp);
VN_LOCK_ASHARE(vp);
VI_UNLOCK(vp);
}
if (ino == udf_getid(&udfmp->root_icb))
vp->v_vflag |= VV_ROOT;

View File

@ -1577,7 +1577,9 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
*/
if (vp->v_type != VFIFO) {
/* FFS supports shared locking for all files except fifos. */
VI_LOCK(vp);
VN_LOCK_ASHARE(vp);
VI_UNLOCK(vp);
}
/*