diff options
author | jhb <jhb@FreeBSD.org> | 2010-07-16 19:20:20 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2010-07-16 19:20:20 +0000 |
commit | ea417bf09acdf5d9f44a16d4325b3b99dda501e3 (patch) | |
tree | 9b1c6ddf4f580be24a7413269d25ce4dbc614e35 /sys/fs | |
parent | c23b0b441a985274551fcb108c06f12593545672 (diff) | |
download | FreeBSD-src-ea417bf09acdf5d9f44a16d4325b3b99dda501e3.zip FreeBSD-src-ea417bf09acdf5d9f44a16d4325b3b99dda501e3.tar.gz |
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
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/cd9660/cd9660_vfsops.c | 2 | ||||
-rw-r--r-- | sys/fs/udf/udf_vfsops.c | 5 |
2 files changed, 6 insertions, 1 deletions
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index e27daf8..b8bc6c6 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -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; } diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index 7be5384..af41043 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -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; |