[DragonFlyBSD - Bug #3407] (New) HAMMER2 freemap_alloc page fault — ignored hammer2_chain_modify() error in freemap_try_alloc
afranke
bugtracker-admin at leaf.dragonflybsd.org
Wed May 6 06:31:33 PDT 2026
Issue #3407 has been reported by afranke.
----------------------------------------
Bug #3407: HAMMER2 freemap_alloc page fault — ignored hammer2_chain_modify() error in freemap_try_alloc
http://bugs.dragonflybsd.org/issues/3407
* Author: afranke
* Status: New
* Priority: Normal
* Target version: 6.6
* Start date: 2026-05-06
----------------------------------------
(authored together with Claude)
h2. Summary
@hammer2_freemap_try_alloc()@ calls @hammer2_chain_modify()@ at three
sites and discards the return value at every one. When
@hammer2_chain_modify()@ fails its internal COW step
(@hammer2_io_bread()@ / @hammer2_io_new()@ returning EIO), it
sets @chain->data = NULL@, @chain->error = HAMMER2_ERROR_EIO@,
and returns the error. Because the caller ignores it, execution
proceeds to @bmap = &chain->data->bmdata[n];@ and the next
@bmap->avail@ read page-faults the kernel.
<pre>
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff80983a29
panic: page fault
Trace:
trap_pfault+0x475
hammer2_freemap_alloc+0x3e9
hammer2_chain_modify+0x60c
</pre>
The fault offset (@0x1c@ = @bmap->avail@ in @hammer2_bmap_data_t@)
matches @hammer2_freemap.c:389@ (`bmap = &chain->data->bmdata[n]; if
(bmap->avail) ...@) with @chain->data == 0`.
h2. Root cause
@hammer2_chain.c:1810@ (the COW I/O-error branch in @hammer2_chain_modify@):
<pre><code class="c">
error = hammer2_io_new(...) | hammer2_io_bread(...);
...
if (error) {
kprintf("hammer2_chain_modify: hmp=%p I/O error\n", hmp);
chain->error = HAMMER2_ERROR_EIO;
...
chain->data = NULL;
break;
}
</code></pre>
The function returns @chain->error@ (EIO).
@hammer2_freemap.c:327, 354, 371@ each call `hammer2_chain_modify(chain,
mtid, 0, 0)` and discard the return. After such a failure
@chain->bref.type@ still holds @HAMMER2_BREF_TYPE_FREEMAP_LEAF@
(KKASSERT at line 367 succeeds), so the scan loop runs and
dereferences @chain->data at .
h2. Fix
Attached patch
@0002-hammer2-freemap-check-modify-error.patch@ captures the return
value at each of the three sites, propagates it as
@HAMMER2_ERROR_EIO@, and skips the scan loop when chain->data
may be NULL.
Build-tested against DragonFly master @ @4f37521524@: applies
clean with @git apply@, hammer2.ko links cleanly under the kernel
`-Werror -Wall -Wredundant-decls -Wnested-externs -Wpointer-arith
-Winit-self -Wundef` set.
h2. Reproduction
n=1 in production: a freshly- at newfs_hammer2@'d ROOT PFS, ~1.5 GB
of cpdup'd content, with concurrent `dd if=/dev/zero of=/dev/X
bs=1m` on a different slice of the same physical disk; the
contention apparently induced an EIO on a HAMMER2 metadata read
or freemap COW write. We have not been able to deterministically
re-trigger the COW failure, but the fix is correct independent of
trigger: any @hammer2_chain_modify()@ EIO during freemap
allocation should propagate, not crash.
A reliable lab reproducer would inject EIO from
@hammer2_io_bread()@ for FREEMAP_LEAF reads via a debug knob;
out of scope for this report.
---Files--------------------------------
0002-hammer2-freemap-check-modify-error.patch (3.47 KB)
--
You have received this notification because you have either subscribed to it, or are involved in it.
To change your notification preferences, please click here: http://bugs.dragonflybsd.org/my/account
More information about the Bugs
mailing list