summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2010-07-16 19:20:20 +0000
committerjhb <jhb@FreeBSD.org>2010-07-16 19:20:20 +0000
commitea417bf09acdf5d9f44a16d4325b3b99dda501e3 (patch)
tree9b1c6ddf4f580be24a7413269d25ce4dbc614e35 /sys/fs
parentc23b0b441a985274551fcb108c06f12593545672 (diff)
downloadFreeBSD-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.c2
-rw-r--r--sys/fs/udf/udf_vfsops.c5
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;
OpenPOWER on IntegriCloud