--- //depot/projects/smpng/sys/fs/fifofs/fifo_vnops.c 2008/03/13 21:35:00 +++ //depot/user/jhb/lock/fs/fifofs/fifo_vnops.c 2008/10/22 22:21:18 @@ -180,10 +180,14 @@ struct file *fp = ap->a_fp; struct socket *rso, *wso; int error; + int ltype; - ASSERT_VOP_ELOCKED(vp, "fifo_open"); + ASSERT_VOP_LOCKED(vp, "fifo_open"); if (fp == NULL) return (EINVAL); + ltype = VOP_ISLOCKED(vp); + if (vp->v_fifoinfo == NULL && ltype != LK_EXCLUSIVE) + vn_lock(vp, LK_UPGRADE | LK_RETRY); if ((fip = vp->v_fifoinfo) == NULL) { MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, cred, td); @@ -257,7 +261,7 @@ VOP_UNLOCK(vp, 0); error = msleep(&fip->fi_readers, &fifo_mtx, PDROP | PCATCH | PSOCK, "fifoor", 0); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, ltype | LK_RETRY); if (error) { fip->fi_readers--; if (fip->fi_readers == 0) { @@ -277,7 +281,7 @@ VOP_UNLOCK(vp, 0); error = msleep(&fip->fi_writers, &fifo_mtx, PDROP | PCATCH | PSOCK, "fifoow", 0); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, ltype | LK_RETRY); if (error) { fip->fi_writers--; if (fip->fi_writers == 0) { --- //depot/projects/smpng/sys/kern/kern_descrip.c 2008/10/21 22:11:05 +++ //depot/user/jhb/lock/kern/kern_descrip.c 2008/10/23 21:14:12 @@ -1241,7 +1241,7 @@ if (vp != NULL) { int vfslocked; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); error = VOP_PATHCONF(vp, uap->name, td->td_retval); VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); --- //depot/projects/smpng/sys/kern/vfs_lookup.c 2008/10/21 22:11:05 +++ //depot/user/jhb/lock/kern/vfs_lookup.c 2008/10/23 03:52:37 @@ -331,12 +331,48 @@ static int compute_cn_lkflags(struct mount *mp, int lkflags) { + if (mp == NULL || ((lkflags & LK_SHARED) && !(mp->mnt_kern_flag & MNTK_LOOKUP_SHARED))) { lkflags &= ~LK_SHARED; lkflags |= LK_EXCLUSIVE; } - return lkflags; + 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); } /* @@ -596,8 +632,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); @@ -797,8 +832,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 (vfslocked && dvfslocked) --- //depot/projects/smpng/sys/kern/vfs_subr.c 2008/10/21 22:11:05 +++ //depot/user/jhb/lock/kern/vfs_subr.c 2008/10/24 18:10:20 @@ -3899,6 +3899,22 @@ } void +vop_setattr_pre(void *ap) +{ +#ifdef DEBUG_VFS_LOCKS + struct vop_setattr_args *a = ap; + + /* + * VOP_SETATTR() normally needs an exclusive lock except for + * the special case of vfs_mark_atime() when a shared lock is + * sufficient. + */ + if (!(a->a_vap->va_flags & VA_MARK_ATIME)) + ASSERT_VOP_ELOCKED(a->a_vp, "VOP_SETATTR"); +#endif +} + +void vop_setattr_post(void *ap, int rc) { struct vop_setattr_args *a = ap; --- //depot/projects/smpng/sys/kern/vfs_syscalls.c 2008/09/17 20:27:47 +++ //depot/user/jhb/lock/kern/vfs_syscalls.c 2008/10/23 21:14:12 @@ -286,8 +286,8 @@ int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, td); error = namei(&nd); if (error) return (error); @@ -368,7 +368,7 @@ return (error); vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); #ifdef AUDIT AUDIT_ARG(vnode, vp, ARG_VNODE1); #endif @@ -736,7 +736,7 @@ VREF(vp); fdrop(fp, td); vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); AUDIT_ARG(vnode, vp, ARG_VNODE1); error = change_dir(vp, td); while (!error && (mp = vp->v_mountedhere) != NULL) { @@ -800,8 +800,8 @@ struct vnode *vp; int vfslocked; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | MPSAFE, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1 | + MPSAFE, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -886,8 +886,8 @@ error = priv_check(td, PRIV_VFS_CHROOT); if (error) return (error); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - UIO_USERSPACE, uap->path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, UIO_USERSPACE, uap->path, td); error = namei(&nd); if (error) goto error; @@ -1938,7 +1938,7 @@ offset += fp->f_offset; break; case L_XTND: - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); error = VOP_GETATTR(vp, &vattr, cred); VOP_UNLOCK(vp, 0); if (error) @@ -2123,8 +2124,8 @@ td->td_ucred = tmpcred; } else cred = tmpcred = td->td_ucred; - NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, fd, td); + NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, fd, td); if ((error = namei(&nd)) != 0) goto out1; vfslocked = NDHASGIANT(&nd); @@ -2490,8 +2491,8 @@ struct nameidata nd; int error, vfslocked; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2566,8 +2567,8 @@ struct nameidata nd; int vfslocked; - NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, fd, td); + NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, fd, td); if ((error = namei(&nd)) != 0) return (error); @@ -2732,7 +2733,7 @@ return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0); #endif @@ -2894,7 +2895,7 @@ return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0); #endif @@ -3072,7 +3073,7 @@ return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0); #endif @@ -3309,7 +3310,7 @@ return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0); #endif --- //depot/projects/smpng/sys/kern/vfs_vnops.c 2008/10/21 22:11:05 +++ //depot/user/jhb/lock/kern/vfs_vnops.c 2008/10/23 16:11:06 @@ -187,6 +187,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) @@ -239,7 +241,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); @@ -284,12 +286,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")); @@ -672,7 +680,7 @@ int error; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); error = vn_stat(vp, sb, active_cred, fp->f_cred, td); VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); --- //depot/projects/smpng/sys/kern/vnode_if.src 2008/09/17 20:27:47 +++ //depot/user/jhb/lock/kern/vnode_if.src 2008/10/24 17:58:56 @@ -133,7 +133,7 @@ }; -%% close vp E E E +%% close vp L L L vop_close { IN struct vnode *vp; @@ -162,7 +162,8 @@ }; -%% setattr vp E E E +%% setattr vp L L L +%! setattr pre vop_setattr_pre %! setattr post vop_setattr_post vop_setattr { --- //depot/projects/smpng/sys/security/audit/audit_arg.c 2008/09/17 20:27:47 +++ //depot/user/jhb/lock/security/audit/audit_arg.c 2008/10/23 20:58:05 @@ -631,7 +631,7 @@ */ vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); audit_arg_vnode(vp, ARG_VNODE1); VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); @@ -849,7 +849,7 @@ vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_SHARED | LK_RETRY); audit_arg_vnode(vp, ARG_VNODE1); VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); --- //depot/projects/smpng/sys/sys/mount.h 2008/09/24 21:56:18 +++ //depot/user/jhb/lock/sys/mount.h 2008/10/23 03:06:27 @@ -295,10 +295,7 @@ #define MNT_BYFSID 0x08000000 /* specify filesystem by ID. */ #define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \ MNT_FORCE | MNT_SNAPSHOT | MNT_BYFSID) -/* - * Still available. - */ -#define MNT_SPARE_0x00000010 0x00000010 + /* * Internal filesystem control flags stored in mnt_kern_flag. * @@ -319,6 +316,7 @@ #define MNTK_ASYNC 0x00000002 /* filtered async flag */ #define MNTK_SOFTDEP 0x00000004 /* async disabled by softdep */ #define MNTK_NOINSMNTQ 0x00000008 /* insmntque is not allowed */ +#define MNTK_EXTENDED_SHARED 0x00000010 /* 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 */ --- //depot/projects/smpng/sys/sys/vnode.h 2008/10/21 22:11:05 +++ //depot/user/jhb/lock/sys/vnode.h 2008/10/24 18:16:32 @@ -676,6 +676,7 @@ void vop_rename_pre(void *a); void vop_rmdir_post(void *a, int rc); void vop_setattr_post(void *a, int rc); +void vop_setattr_pre(void *a); void vop_strategy_pre(void *a); void vop_symlink_post(void *a, int rc); void vop_unlock_post(void *a, int rc); --- //depot/projects/smpng/sys/ufs/ffs/ffs_vfsops.c 2008/10/21 22:11:05 +++ //depot/user/jhb/lock/ufs/ffs/ffs_vfsops.c 2008/10/23 20:06:26 @@ -883,6 +883,9 @@ */ MNT_ILOCK(mp); mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED; +#ifndef NO_UFS_EXTENDED_SHARED + mp->mnt_kern_flag |= MNTK_EXTENDED_SHARED; +#endif MNT_IUNLOCK(mp); #ifdef UFS_EXTATTR #ifdef UFS_EXTATTR_AUTOSTART @@ -1423,10 +1426,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; @@ -1499,6 +1501,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 --- //depot/projects/smpng/sys/ufs/ufs/ufs_vnops.c 2008/09/24 21:56:18 +++ //depot/user/jhb/lock/ufs/ufs/ufs_vnops.c 2008/10/24 14:22:31 @@ -488,7 +488,9 @@ * checks get handled by other levels (e.g., ffs_update()). */ if (vap->va_vaflags & VA_MARK_ATIME) { + VI_LOCK(vp); ip->i_flag |= IN_ACCESS; + VI_UNLOCK(vp); return (0); } if (vap->va_flags != VNOVAL) { --- //depot/projects/smpng/sys/vm/vm_mmap.c 2008/09/24 21:56:18 +++ //depot/user/jhb/lock/vm/vm_mmap.c 2008/10/23 19:03:09 @@ -1164,7 +1164,7 @@ mp = vp->v_mount; cred = td->td_ucred; vfslocked = VFS_LOCK_GIANT(mp); - if ((error = vget(vp, LK_EXCLUSIVE, td)) != 0) { + if ((error = vget(vp, LK_SHARED, td)) != 0) { VFS_UNLOCK_GIANT(vfslocked); return (error); } @@ -1181,7 +1181,7 @@ if (obj->handle != vp) { vput(vp); vp = (struct vnode*)obj->handle; - vget(vp, LK_EXCLUSIVE, td); + vget(vp, LK_SHARED, td); } type = OBJT_VNODE; handle = vp;