Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.c +++ sys/fs/tmpfs/tmpfs_vnops.c @@ -1632,6 +1632,9 @@ .vop_whiteout = tmpfs_whiteout, .vop_bmap = VOP_EOPNOTSUPP, .vop_vptocnp = tmpfs_vptocnp, + .vop_lock1 = vop_lock, + .vop_unlock = vop_unlock, + .vop_islocked = vop_islocked, }; /* Index: sys/kern/kern_lock.c =================================================================== --- sys/kern/kern_lock.c +++ sys/kern/kern_lock.c @@ -1156,6 +1156,77 @@ return (0); } +int +lockmgr_slock(struct lock *lk, u_int flags, const char *file, int line) +{ + uintptr_t x; + + MPASS((flags & LK_TYPE_MASK) == LK_SHARED); + MPASS((flags & LK_INTERLOCK) == 0); + MPASS((lk->lock_object.lo_flags & LK_NOSHARE) == 0); + + if (LK_CAN_WITNESS(flags)) + WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER, + file, line, NULL); + if (__predict_true(lockmgr_slock_try(lk, &x, flags, true))) { + lockmgr_note_shared_acquire(lk, 0, 0, file, line, flags); + return (0); + } + + return (lockmgr_slock_hard(lk, flags, NULL, file, line, NULL)); +} + +int +lockmgr_xlock(struct lock *lk, u_int flags, const char *file, int line) +{ + uintptr_t tid; + + MPASS((flags & LK_TYPE_MASK) == LK_EXCLUSIVE); + MPASS((flags & LK_INTERLOCK) == 0); + + if (LK_CAN_WITNESS(flags)) + WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER | + LOP_EXCLUSIVE, file, line, NULL); + tid = (uintptr_t)curthread; + if (atomic_cmpset_acq_ptr(&lk->lk_lock, LK_UNLOCKED, tid)) { + lockmgr_note_exclusive_acquire(lk, 0, 0, file, line, + flags); + return (0); + } + + return (lockmgr_xlock_hard(lk, flags, NULL, file, line, NULL)); +} + +int +lockmgr_unlock(struct lock *lk) +{ + uintptr_t x, tid; + const char *file; + int line; + + file = __FILE__; + line = __LINE__; + + _lockmgr_assert(lk, KA_LOCKED, file, line); + x = lk->lk_lock; + if (__predict_true(x & LK_SHARE) != 0) { + if (lockmgr_sunlock_try(lk, &x)) { + lockmgr_note_shared_release(lk, file, line); + } else { + return (lockmgr_sunlock_hard(lk, x, LK_RELEASE, NULL, file, line)); + } + } else { + tid = (uintptr_t)curthread; + if (!lockmgr_recursed(lk) && + atomic_cmpset_rel_ptr(&lk->lk_lock, tid, LK_UNLOCKED)) { + lockmgr_note_exclusive_release(lk, file, line); + } else { + return (lockmgr_xunlock_hard(lk, x, LK_RELEASE, NULL, file, line)); + } + } + return (0); +} + int __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, const char *wmesg, int pri, int timo, const char *file, int line) Index: sys/kern/vfs_default.c =================================================================== --- sys/kern/vfs_default.c +++ sys/kern/vfs_default.c @@ -544,6 +544,72 @@ return (lockstatus(ap->a_vp->v_vnlock)); } +/* + * Variants of the above set. + * + * Differences are: + * - shared locking disablement is not supported + * - v_vnlock pointer is not honored + */ +int +vop_lock(ap) + struct vop_lock1_args /* { + struct vnode *a_vp; + int a_flags; + char *file; + int line; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + int flags = ap->a_flags; + struct mtx *ilk; + + MPASS(vp->v_vnlock == &vp->v_lock); + + if (__predict_false((flags & ~(LK_TYPE_MASK | LK_NODDLKTREAT | LK_RETRY)) != 0)) + goto other; + + switch (flags & LK_TYPE_MASK) { + case LK_SHARED: + MPASS((vp->v_lock.lock_object.lo_flags & LK_NOSHARE) == 0); + return (lockmgr_slock(&vp->v_lock, flags, ap->a_file, ap->a_line)); + case LK_EXCLUSIVE: + return (lockmgr_xlock(&vp->v_lock, flags, ap->a_file, ap->a_line)); + } +other: + ilk = VI_MTX(vp); + return (lockmgr_lock_fast_path(&vp->v_lock, flags, + &ilk->lock_object, ap->a_file, ap->a_line)); +} + +int +vop_unlock(ap) + struct vop_unlock_args /* { + struct vnode *a_vp; + int a_flags; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + + MPASS(vp->v_vnlock == &vp->v_lock); + MPASS(ap->a_flags == 0); + + return (lockmgr_unlock(&vp->v_lock)); +} + +int +vop_islocked(ap) + struct vop_islocked_args /* { + struct vnode *a_vp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + + MPASS(vp->v_vnlock == &vp->v_lock); + + return (lockstatus(&vp->v_lock)); +} + /* * Return true for select/poll. */ Index: sys/sys/lockmgr.h =================================================================== --- sys/sys/lockmgr.h +++ sys/sys/lockmgr.h @@ -74,6 +74,10 @@ struct lock_object *ilk, const char *file, int line); int lockmgr_unlock_fast_path(struct lock *lk, u_int flags, struct lock_object *ilk); +int lockmgr_slock(struct lock *lk, u_int flags, const char *file, int line); +int lockmgr_xlock(struct lock *lk, u_int flags, const char *file, int line); +int lockmgr_unlock(struct lock *lk); + #if defined(INVARIANTS) || defined(INVARIANT_SUPPORT) void _lockmgr_assert(const struct lock *lk, int what, const char *file, int line); #endif Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -761,11 +761,14 @@ int vop_stdgetpages(struct vop_getpages_args *); int vop_stdinactive(struct vop_inactive_args *); int vop_stdneed_inactive(struct vop_need_inactive_args *); -int vop_stdislocked(struct vop_islocked_args *); int vop_stdkqfilter(struct vop_kqfilter_args *); int vop_stdlock(struct vop_lock1_args *); -int vop_stdputpages(struct vop_putpages_args *); int vop_stdunlock(struct vop_unlock_args *); +int vop_stdislocked(struct vop_islocked_args *); +int vop_lock(struct vop_lock1_args *); +int vop_unlock(struct vop_unlock_args *); +int vop_islocked(struct vop_islocked_args *); +int vop_stdputpages(struct vop_putpages_args *); int vop_nopoll(struct vop_poll_args *); int vop_stdaccess(struct vop_access_args *ap); int vop_stdaccessx(struct vop_accessx_args *ap);