Index: sys/kern/subr_witness.c =================================================================== --- sys/kern/subr_witness.c +++ sys/kern/subr_witness.c @@ -358,6 +358,8 @@ static void witness_list_lock(struct lock_instance *instance, int (*prnt)(const char *fmt, ...)); static int witness_output(const char *fmt, ...) __printflike(1, 2); +static int witness_output_drain(void *arg __unused, const char *data, + int len); static int witness_voutput(const char *fmt, va_list ap) __printflike(1, 0); static void witness_setflag(struct lock_object *lock, int flag, int set); @@ -1281,6 +1283,9 @@ for (j = 0, lle = lock_list; lle != NULL; lle = lle->ll_next) { for (i = lle->ll_count - 1; i >= 0; i--, j++) { + struct witness_lock_order_data *data; + struct stack pstack; + bool pstackv; MPASS(j < LOCK_CHILDCOUNT * LOCK_NCHILDREN); lock1 = &lle->ll_children[i]; @@ -1367,6 +1372,17 @@ */ if (blessed(w, w1)) goto out; + + if (witness_trace) { + pstackv = false; + data = witness_lock_order_get(w, w1); + if (data != NULL) { + stack_copy(&data->wlod_stack, + &pstack); + pstackv = true; + } + data = NULL; + } mtx_unlock_spin(&w_mtx); #ifdef WITNESS_NO_VNODE @@ -1434,6 +1450,24 @@ lock->lo_name, w->w_name, fixup_filename(file), line); } + if (witness_trace && pstackv) { + char buf[32]; + struct sbuf sb; + + sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); + sbuf_set_drain(&sb, witness_output_drain, + NULL); + + witness_output( + "Lock order \"%s\"(%s) -> \"%s\"(%s) first seen at:\n", + w->w_name, w->w_class->lc_name, + w1->w_name, w1->w_class->lc_name); + stack_sbuf_print_flags(&sb, &pstack, M_NOWAIT, + STACK_SBUF_FMT_LONG); + + sbuf_finish(&sb); + sbuf_delete(&sb); + } witness_debugger(1, __func__); return; }