DF-0839 / fix_run.log
=== FIX KERNEL: DragonFly 6.5-DEVELOPMENT #2: Sat Jul 11 08:35:16 UTC 2026 === sha256(/boot/kernel/kernel) = 6c3d295abf45bc8d9fa384562f0e25768ad8dafd7776c54f43ee4db52fdeeccf === Run 1: HAMMER v3 -> v4 clean upgrade (exercises lock acquire + fixed release path) === [probe] issuing HAMMERIOC_SET_VERSION(cur=4) on /mnt/htest/testfile (fd=3) [probe] ioctl rc=0 errno=0 (Undefined error: 0) head.error=0 head.flags=0x0 [probe] undo-upgrade succeeded (no leak this run) RUN_EXIT=0 guest_status=up version_after=current=4 === Run 2: v4->v4 noop (version already set, returns 0 at line 624-625, no locks acquired) === [probe] issuing HAMMERIOC_SET_VERSION(cur=4) on /mnt/htest/testfile (fd=3) [probe] ioctl rc=0 errno=0 (Undefined error: 0) head.error=0 head.flags=0x0 RUN2_EXIT=0 guest_status=up === Disassembly verification (hammer_ioctl.o, patched) === Error path after hammer_upgrade_undo_4 fails: 1827: mov %r15d,0x144(%r13) # hmp->version = over (restore in-memory version) 182e: jmpq 13df # jump to shared unlock sequence Shared unlock (both error and success paths): 13df: lea -0x198(%rbp),%rdi # trans 13e6: callq hammer_sync_unlock # release sync_lock 13eb: mov -0x1a8(%rbp),%rdi # &hmp->flusher.finalize_lock 13f2: callq hammer_unlock # release finalize_lock 13f7: mov -0x160(%rbp),%eax # error 13fd: jmpq 642 # goto failed: (ver->head.error=error; done_cursor; return 0) The compiler merged the unlock sequences from both the error path (my fix) and the success path into a single shared code block at 0x13df. Both paths now release both locks before reaching the failed: cleanup label. The lock leak is eliminated.