Date: Fri, 16 Jul 2010 20:23:25 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r210173 - in stable/7/sys: cddl/contrib/opensolaris/uts/common/fs/zfs fs/cd9660 fs/udf ufs/ffs Message-ID: <201007162023.o6GKNP18012503@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Fri Jul 16 20:23:24 2010 New Revision: 210173 URL: http://svn.freebsd.org/changeset/base/210173 Log: 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 into 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. The softupdates code also toggles LK_NOSHARE in one function to close a race with snapshots. Fix this code to grab the interlock while fiddling with lk_flags. Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c stable/7/sys/fs/cd9660/cd9660_vfsops.c stable/7/sys/fs/udf/udf_vfsops.c stable/7/sys/ufs/ffs/ffs_softdep.c stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c ============================================================================== --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Fri Jul 16 19:52:03 2010 (r210172) +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Fri Jul 16 20:23:24 2010 (r210173) @@ -618,8 +618,11 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_bu vp->v_op = &zfs_fifoops; 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); Modified: stable/7/sys/fs/cd9660/cd9660_vfsops.c ============================================================================== --- stable/7/sys/fs/cd9660/cd9660_vfsops.c Fri Jul 16 19:52:03 2010 (r210172) +++ stable/7/sys/fs/cd9660/cd9660_vfsops.c Fri Jul 16 20:23:24 2010 (r210173) @@ -821,7 +821,9 @@ cd9660_vget_internal(mp, ino, flags, vpp vp->v_op = &cd9660_fifoops; break; default: - vp->v_vnlock->lk_flags &= ~LK_NOSHARE; + VI_LOCK(vp); + VN_LOCK_ASHARE(vp); + VI_UNLOCK(vp); break; } Modified: stable/7/sys/fs/udf/udf_vfsops.c ============================================================================== --- stable/7/sys/fs/udf/udf_vfsops.c Fri Jul 16 19:52:03 2010 (r210172) +++ stable/7/sys/fs/udf/udf_vfsops.c Fri Jul 16 20:23:24 2010 (r210173) @@ -709,8 +709,11 @@ udf_vget(struct mount *mp, ino_t ino, in 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; Modified: stable/7/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_softdep.c Fri Jul 16 19:52:03 2010 (r210172) +++ stable/7/sys/ufs/ffs/ffs_softdep.c Fri Jul 16 20:23:24 2010 (r210173) @@ -5291,7 +5291,9 @@ top: return (0); loop: /* While syncing snapshots, we must allow recursive lookups */ + mtx_lock(bp->b_lock.lk_interlock); bp->b_lock.lk_flags |= LK_CANRECURSE; + mtx_unlock(bp->b_lock.lk_interlock); ACQUIRE_LOCK(&lk); /* * As we hold the buffer locked, none of its dependencies @@ -5433,7 +5435,9 @@ loop: /* We reach here only in error and unlocked */ if (error == 0) panic("softdep_sync_metadata: zero error"); + mtx_lock(bp->b_lock.lk_interlock); bp->b_lock.lk_flags &= ~LK_CANRECURSE; + mtx_unlock(bp->b_lock.lk_interlock); bawrite(bp); return (error); } @@ -5445,7 +5449,9 @@ loop: break; } VI_UNLOCK(vp); + mtx_lock(bp->b_lock.lk_interlock); bp->b_lock.lk_flags &= ~LK_CANRECURSE; + mtx_unlock(bp->b_lock.lk_interlock); bawrite(bp); if (nbp != NULL) { bp = nbp; Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Fri Jul 16 19:52:03 2010 (r210172) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Fri Jul 16 20:23:24 2010 (r210173) @@ -1519,7 +1519,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); } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007162023.o6GKNP18012503>