[DragonFlyBSD - Bug #3407] (Resolved) HAMMER2 freemap_alloc page fault — ignored hammer2_chain_modify() error in freemap_try_alloc
dillon
bugtracker-admin at leaf.dragonflybsd.org
Wed May 6 22:15:56 PDT 2026
Issue #3407 has been updated by dillon.
Category set to Kernel
Status changed from New to Resolved
Assignee set to dillon
Committed more or less as supplied.
Note that the freemap does not actually allocate blocks, they are reserved at filesystem creation time and generated algorithmically, so it isn't generally possible for hammer2_chain_modify() to return an error when the block is successfully read prior to being modified.
However, with enough corruption of the block data the function can return an error so the processing of the error condition is accepted as supplied.
----------------------------------------
Bug #3407: HAMMER2 freemap_alloc page fault — ignored hammer2_chain_modify() error in freemap_try_alloc
http://bugs.dragonflybsd.org/issues/3407#change-14660
* Author: afranke
* Status: Resolved
* Priority: Normal
* Assignee: dillon
* Category: Kernel
* 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