git: 8583840cfb92 - stable/13 - witness: Record the first acquired file and line for recursable locks

From: Zhenlei Huang <zlei_at_FreeBSD.org>
Date: Sat, 04 Oct 2025 16:44:48 UTC
The branch stable/13 has been updated by zlei:

URL: https://cgit.FreeBSD.org/src/commit/?id=8583840cfb925eeafac8eff171029a56f7c9c133

commit 8583840cfb925eeafac8eff171029a56f7c9c133
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2025-09-17 16:48:54 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2025-10-04 16:43:28 +0000

    witness: Record the first acquired file and line for recursable locks
    
    and the last acquired file and line to witness object.
    
    For recursable locks, unfortunately current implementation records only
    the recurse count and the last acquired file and line, but does not
    restore the previous acquired file and line on unlock. Hence it is
    possible to report false acquired file and line, and that may mislead
    developers and make the report by users a little harder to analyse.
    
    Since subsequent recurse locks do not affect how witness order check,
    record the first acquired file and line so that the logic is much clear.
    
    Reported by:    bz
    Reviewed by:    kib (previous version), markj
    See also:       https://lists.freebsd.org/archives/freebsd-current/2025-June/007944.html
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D52496
    
    (cherry picked from commit 2d85bc89294baa04daf509e81ec3880bff79cc10)
    (cherry picked from commit 3dc9f96a489cd53710af8205a1f3901c11b760a5)
    (cherry picked from commit 7838ad85fb1a75464e53525b4cdb064ca1e97a47)
---
 sys/kern/subr_witness.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 5ee72e68ac26..91055b604a5c 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -1512,6 +1512,10 @@ witness_lock(struct lock_object *lock, int flags, const char *file, int line)
 	else
 		lock_list = PCPU_PTR(spinlocks);
 
+	/* Update per-witness last file and line acquire. */
+	w->w_file = file;
+	w->w_line = line;
+
 	/* Check to see if we are recursing on a lock we already own. */
 	instance = find_instance(*lock_list, lock);
 	if (instance != NULL) {
@@ -1519,15 +1523,9 @@ witness_lock(struct lock_object *lock, int flags, const char *file, int line)
 		CTR4(KTR_WITNESS, "%s: pid %d recursed on %s r=%d", __func__,
 		    td->td_proc->p_pid, lock->lo_name,
 		    instance->li_flags & LI_RECURSEMASK);
-		instance->li_file = file;
-		instance->li_line = line;
 		return;
 	}
 
-	/* Update per-witness last file and line acquire. */
-	w->w_file = file;
-	w->w_line = line;
-
 	/* Find the next open lock instance in the list and fill it. */
 	lle = *lock_list;
 	if (lle == NULL || lle->ll_count == LOCK_NCHILDREN) {