--- //depot/projects/smpng/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c 2009/01/28 22:38:17 +++ //depot/user/jhb/lock/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c 2009/01/28 23:05:44 @@ -153,7 +153,6 @@ zp->z_vnode = vp; vp->v_data = (caddr_t)zp; VN_LOCK_AREC(vp); - VN_LOCK_ASHARE(vp); list_link_init(&zp->z_link_node); @@ -610,6 +609,8 @@ vp->v_op = &zfs_fifoops; break; } + if (vp->v_type != VFIFO) + VN_LOCK_ASHARE(vp); mutex_enter(&zfsvfs->z_znodes_lock); list_insert_tail(&zfsvfs->z_all_znodes, zp); @@ -1491,6 +1492,7 @@ vp = ZTOV(rootzp); vp->v_type = VDIR; + VN_LOCK_ASHARE(vp); bzero(&zfsvfs, sizeof (zfsvfs_t)); --- //depot/projects/smpng/sys/dev/md/md.c 2009/02/23 18:46:27 +++ //depot/user/jhb/lock/dev/md/md.c 2009/02/23 19:02:01 @@ -924,12 +924,20 @@ return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_vp->v_type != VREG || - (error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred))) { - VOP_UNLOCK(nd.ni_vp, 0); - (void)vn_close(nd.ni_vp, flags, td->td_ucred, td); - VFS_UNLOCK_GIANT(vfslocked); - return (error ? error : EINVAL); + if (nd.ni_vp->v_type != VREG) { + error = EINVAL; + goto bad; + } + error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred); + if (error != 0) + goto bad; + if (VOP_ISLOCKED(nd.ni_vp) != LK_EXCLUSIVE) { + vn_lock(nd.ni_vp, LK_UPGRADE | LK_RETRY); + if (nd.ni_vp->v_iflag & VI_DOOMED) { + /* Forced unmount. */ + error = EBADF; + goto bad; + } } nd.ni_vp->v_vflag |= VV_MD; VOP_UNLOCK(nd.ni_vp, 0); @@ -948,13 +956,15 @@ sc->vnode = NULL; vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); nd.ni_vp->v_vflag &= ~VV_MD; - VOP_UNLOCK(nd.ni_vp, 0); - (void)vn_close(nd.ni_vp, flags, td->td_ucred, td); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + goto bad; } VFS_UNLOCK_GIANT(vfslocked); return (0); +bad: + VOP_UNLOCK(nd.ni_vp, 0); + (void)vn_close(nd.ni_vp, flags, td->td_ucred, td); + VFS_UNLOCK_GIANT(vfslocked); + return (error); } static int --- //depot/projects/smpng/sys/fs/cd9660/cd9660_vfsops.c 2009/02/13 18:22:54 +++ //depot/user/jhb/lock/fs/cd9660/cd9660_vfsops.c 2009/02/13 20:21:57 @@ -371,7 +372,8 @@ mp->mnt_maxsymlinklen = 0; MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; - mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED; + mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED | + MNTK_EXTENDED_SHARED; MNT_IUNLOCK(mp); isomp->im_mountp = mp; isomp->im_dev = dev; --- //depot/projects/smpng/sys/fs/udf/udf_vfsops.c 2009/02/27 15:49:22 +++ //depot/user/jhb/lock/fs/udf/udf_vfsops.c 2009/02/27 16:32:01 @@ -353,7 +354,8 @@ mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; - mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED; + mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED | + MNTK_EXTENDED_SHARED; MNT_IUNLOCK(mp); udfmp->im_mountp = mp; udfmp->im_dev = dev; --- //depot/projects/smpng/sys/kern/vfs_lookup.c 2009/01/15 22:41:24 +++ //depot/user/jhb/lock/kern/vfs_lookup.c 2009/01/16 13:17:12 @@ -353,6 +353,41 @@ return (lkflags); } +static __inline int +needs_exclusive_leaf(struct mount *mp, int flags) +{ + + /* + * Intermediate nodes can use shared locks, we only need to + * force an exclusive lock for leaf nodes. + */ + if ((flags & (ISLASTCN | LOCKLEAF)) != (ISLASTCN | LOCKLEAF)) + return (0); + + /* Always use exclusive locks if LOCKSHARED isn't set. */ + if (!(flags & LOCKSHARED)) + return (1); + + /* + * For lookups during open(), if the mount point supports + * extended shared operations, then use a shared lock for the + * leaf node, otherwise use an exclusive lock. + */ + if (flags & ISOPEN) { + if (mp != NULL && + (mp->mnt_kern_flag & MNTK_EXTENDED_SHARED)) + return (0); + else + return (1); + } + + /* + * Lookup requests outside of open() that specify LOCKSHARED + * only need a shared lock on the leaf vnode. + */ + return (1); +} + /* * Search a pathname. * This is a very central and rather complicated routine. @@ -610,8 +645,7 @@ * If we're looking up the last component and we need an exclusive * lock, adjust our lkflags. */ - if ((cnp->cn_flags & (ISLASTCN|LOCKSHARED|LOCKLEAF)) == - (ISLASTCN|LOCKLEAF)) + if (needs_exclusive_leaf(dp->v_mount, cnp->cn_flags)) cnp->cn_lkflags = LK_EXCLUSIVE; #ifdef NAMEI_DIAGNOSTIC vprint("lookup in", dp); @@ -811,8 +845,8 @@ * Because of lookup_shared we may have the vnode shared locked, but * the caller may want it to be exclusively locked. */ - if ((cnp->cn_flags & (ISLASTCN | LOCKSHARED | LOCKLEAF)) == - (ISLASTCN | LOCKLEAF) && VOP_ISLOCKED(dp) != LK_EXCLUSIVE) { + if (needs_exclusive_leaf(dp->v_mount, cnp->cn_flags) && + VOP_ISLOCKED(dp) != LK_EXCLUSIVE) { vn_lock(dp, LK_UPGRADE | LK_RETRY); if (dp->v_iflag & VI_DOOMED) { error = ENOENT; --- //depot/projects/smpng/sys/kern/vfs_vnops.c 2009/01/21 21:09:25 +++ //depot/user/jhb/lock/kern/vfs_vnops.c 2009/01/21 21:15:47 @@ -188,6 +188,8 @@ ndp->ni_cnd.cn_flags = ISOPEN | ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF | MPSAFE | AUDITVNODE1; + if (!(fmode & FWRITE)) + ndp->ni_cnd.cn_flags |= LOCKSHARED; if ((error = namei(ndp)) != 0) return (error); if (!mpsafe) @@ -240,7 +242,7 @@ if (fmode & FWRITE) vp->v_writecount++; *flagp = fmode; - ASSERT_VOP_ELOCKED(vp, "vn_open_cred"); + ASSERT_VOP_LOCKED(vp, "vn_open_cred"); if (!mpsafe) VFS_UNLOCK_GIANT(vfslocked); return (0); @@ -285,12 +287,18 @@ struct thread *td; { struct mount *mp; - int error; + int error, lock_flags; + + if (!(flags & FWRITE) && vp->v_mount != NULL && + vp->v_mount->mnt_kern_flag & MNTK_EXTENDED_SHARED) + lock_flags = LK_SHARED; + else + lock_flags = LK_EXCLUSIVE; VFS_ASSERT_GIANT(vp->v_mount); vn_start_write(vp, &mp, V_WAIT); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, lock_flags | LK_RETRY); if (flags & FWRITE) { VNASSERT(vp->v_writecount > 0, vp, ("vn_close: negative writecount")); --- //depot/projects/smpng/sys/kern/vnode_if.src 2009/01/21 21:09:25 +++ //depot/user/jhb/lock/kern/vnode_if.src 2009/01/21 21:15:47 @@ -133,7 +133,7 @@ }; -%% close vp E E E +%% close vp L L L vop_close { IN struct vnode *vp; --- //depot/projects/smpng/sys/sys/mount.h 2009/02/09 16:14:58 +++ //depot/user/jhb/lock/sys/mount.h 2009/02/09 17:56:53 @@ -318,14 +318,15 @@ #define MNTK_NOINSMNTQ 0x00000008 /* insmntque is not allowed */ #define MNTK_DRAINING 0x00000010 /* lock draining is happening */ #define MNTK_REFEXPIRE 0x00000020 /* refcount expiring is happening */ +#define MNTK_EXTENDED_SHARED 0x00000040 /* Allow shared locking for more ops */ #define MNTK_UNMOUNT 0x01000000 /* unmount in progress */ #define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */ #define MNTK_SUSPEND 0x08000000 /* request write suspension */ #define MNTK_SUSPEND2 0x04000000 /* block secondary writes */ #define MNTK_SUSPENDED 0x10000000 /* write operations are suspended */ #define MNTK_MPSAFE 0x20000000 /* Filesystem is MPSAFE. */ +#define MNTK_LOOKUP_SHARED 0x40000000 /* FS supports shared lock lookups */ #define MNTK_NOKNOTE 0x80000000 /* Don't send KNOTEs from VOP hooks */ -#define MNTK_LOOKUP_SHARED 0x40000000 /* FS supports shared lock lookups */ /* * Sysctl CTL_VFS definitions. --- //depot/projects/smpng/sys/ufs/ffs/ffs_vfsops.c 2009/02/27 15:49:22 +++ //depot/user/jhb/lock/ufs/ffs/ffs_vfsops.c 2009/02/27 16:32:01 @@ -883,7 +883,8 @@ * Initialize filesystem stat information in mount struct. */ MNT_ILOCK(mp); - mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED; + mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED | + MNTK_EXTENDED_SHARED; MNT_IUNLOCK(mp); #ifdef UFS_EXTATTR #ifdef UFS_EXTATTR_AUTOSTART @@ -1440,10 +1441,9 @@ return (error); } /* - * FFS supports recursive and shared locking. + * FFS supports recursive locking. */ VN_LOCK_AREC(vp); - VN_LOCK_ASHARE(vp); vp->v_data = ip; vp->v_bufobj.bo_bsize = fs->fs_bsize; ip->i_vnode = vp; @@ -1516,6 +1516,10 @@ /* * Finish inode initialization. */ + if (vp->v_type != VFIFO) { + /* FFS supports shared locking for all files except fifos. */ + VN_LOCK_ASHARE(vp); + } /* * Set up a generation number for this inode if it does not