diff --git a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h --- a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h +++ b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h @@ -103,7 +103,7 @@ }; #define ZFS_TEARDOWN_INIT(zfsvfs) \ - rms_init(&(zfsvfs)->z_teardown_lock, "zfs teardown") + rms_init_flags(&(zfsvfs)->z_teardown_lock, "zfs teardown", RMS_DUPOK) #define ZFS_TEARDOWN_DESTROY(zfsvfs) \ rms_destroy(&(zfsvfs)->z_teardown_lock) diff --git a/sys/kern/kern_rmlock.c b/sys/kern/kern_rmlock.c --- a/sys/kern/kern_rmlock.c +++ b/sys/kern/kern_rmlock.c @@ -982,13 +982,26 @@ void rms_init(struct rmslock *rms, const char *name) { + rms_init_flags(rms, name, 0); +} + +void +rms_init_flags(struct rmslock *rms, const char *name, int opts) +{ + int flags; rms->owner = RMS_NOOWNER; rms->writers = 0; rms->readers = 0; rms->debug_readers = 0; - mtx_init(&rms->mtx, name, NULL, MTX_DEF | MTX_NEW); + mtx_init(&rms->mtx, "rms_mtx", NULL, MTX_DEF | MTX_NEW); rms->pcpu = uma_zalloc_pcpu(pcpu_zone_8, M_WAITOK | M_ZERO); + + flags = LO_WITNESS | LO_SLEEPABLE; + if (opts & RMS_DUPOK) + flags |= LO_DUPOK; + lock_init(&rms->lock_object, &lock_class_rm_sleepable, name, NULL, + flags); } void @@ -1015,6 +1028,8 @@ rms_int_readers_inc(rms, rms_int_pcpu(rms)); mtx_unlock(&rms->mtx); critical_exit(); + + WITNESS_LOCK(&rms->lock_object, 0, __FILE__, __LINE__); TD_LOCKS_INC(curthread); } @@ -1026,6 +1041,9 @@ rms_assert_rlock_ok(rms); MPASS(atomic_load_ptr(&rms->owner) != curthread); + WITNESS_CHECKORDER(&rms->lock_object, LOP_NEWORDER, __FILE__, __LINE__, + NULL); + critical_enter(); pcpu = rms_int_pcpu(rms); rms_int_influx_enter(rms, pcpu); @@ -1039,6 +1057,8 @@ atomic_interrupt_fence(); rms_int_influx_exit(rms, pcpu); critical_exit(); + + WITNESS_LOCK(&rms->lock_object, 0, __FILE__, __LINE__); TD_LOCKS_INC(curthread); } @@ -1063,6 +1083,8 @@ atomic_interrupt_fence(); rms_int_influx_exit(rms, pcpu); critical_exit(); + + WITNESS_LOCK(&rms->lock_object, 0, __FILE__, __LINE__); TD_LOCKS_INC(curthread); return (1); } @@ -1083,6 +1105,8 @@ if (rms->readers == 0) wakeup_one(&rms->writers); mtx_unlock(&rms->mtx); + + WITNESS_UNLOCK(&rms->lock_object, 0, __FILE__, __LINE__); TD_LOCKS_DEC(curthread); } @@ -1104,6 +1128,8 @@ atomic_interrupt_fence(); rms_int_influx_exit(rms, pcpu); critical_exit(); + + WITNESS_UNLOCK(&rms->lock_object, 0, __FILE__, __LINE__); TD_LOCKS_DEC(curthread); } @@ -1194,6 +1220,9 @@ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__); MPASS(atomic_load_ptr(&rms->owner) != curthread); + WITNESS_CHECKORDER(&rms->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, + __FILE__, __LINE__, NULL); + mtx_lock(&rms->mtx); rms->writers++; if (rms->writers > 1) { @@ -1222,6 +1251,8 @@ rms_assert_no_pcpu_readers(rms); mtx_unlock(&rms->mtx); MPASS(rms->readers == 0); + + WITNESS_LOCK(&rms->lock_object, LOP_EXCLUSIVE, __FILE__, __LINE__); TD_LOCKS_INC(curthread); } @@ -1243,6 +1274,8 @@ rms->owner = RMS_NOOWNER; } mtx_unlock(&rms->mtx); + + WITNESS_UNLOCK(&rms->lock_object, LOP_EXCLUSIVE, __FILE__, __LINE__); TD_LOCKS_DEC(curthread); } diff --git a/sys/sys/_rmlock.h b/sys/sys/_rmlock.h --- a/sys/sys/_rmlock.h +++ b/sys/sys/_rmlock.h @@ -71,6 +71,7 @@ struct rmslock_pcpu; struct rmslock { + struct lock_object lock_object; struct mtx mtx; struct thread *owner; struct rmslock_pcpu *pcpu; diff --git a/sys/sys/param.h b/sys/sys/param.h --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -73,7 +73,7 @@ * cannot include sys/param.h and should only be updated here. */ #undef __FreeBSD_version -#define __FreeBSD_version 1500025 +#define __FreeBSD_version 1500026 /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/rmlock.h b/sys/sys/rmlock.h --- a/sys/sys/rmlock.h +++ b/sys/sys/rmlock.h @@ -132,7 +132,10 @@ #define rm_assert(rm, what) #endif +#define RMS_DUPOK RM_DUPOK + void rms_init(struct rmslock *rms, const char *name); +void rms_init_flags(struct rmslock *rms, const char *name, int opts); void rms_destroy(struct rmslock *rms); void rms_rlock(struct rmslock *rms); int rms_try_rlock(struct rmslock *rms);