This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Hurd".
The branch, master has been updated
via a1520349d38e9b7449454345e19f3e58c203b9e6 (commit)
from d33db17a9cdd58c67b8d8238fcc577fb80ac5c5b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a1520349d38e9b7449454345e19f3e58c203b9e6
Author: Milos Nikic <[email protected]>
Date: Mon Oct 5 20:00:18 2026 +0200
ext2fs journal: Fix regression
trunc_indirect now calls journal_get_write_access on an indirect block
before it knows whether the block will survive the truncate. When the
block is freed entirely, it stays in the running transaction.
ext2_free_blocks clears the bitmap at once, so the allocator can give
the block to a new file before the transaction commits. The new file's
pager writes of that block are then intercepted, since the block is in
the transaction, and after the commit the intercept flush writes the
shadow copy home: the old block pointers, over the new file's data. The
page in memory stays correct and clean, so the damage shows only after
it is evicted or after a reboot.
I hit it with an apt upgrade of an old Hurd image (most libraries get
replaced); the system no longer boots afterwards. With the fix below
the same upgrade completes cleanly.
The fix reserves the indirect block only when it survives, which
restores the old behaviour of never journaling a block that truncate
frees. Reserving after the edit is safe there, because the thread's
open handle keeps the commit from copying the block until the handle
is released.
The underlying hazard is older than this patch: a freed block can be
reused before the transaction freeing it commits, so a journal copy of
its old contents can still land on its new owner (a block allocated
and freed in one transaction, copies in older transactions, or replay).
ext3/ext4 avoid this by keeping freed blocks unavailable until the free
commits.
This same reuse is also why the orphan list currently clears i_size,
i_blocks and i_block[] of an orphan inode on disk, and why write_node
leaves those fields alone while the inode is on the list: it keeps a
reused block from being reached through the orphan's block map. That
workaround costs us: recovery and e2fsck then see an orphan with no
blocks, and the blocks leak until a full fsck. Once freed blocks stay
busy until their free commits, the workaround is no longer needed, and
the series will drop it and keep the block map on disk as ext3/ext4 do.
I also added an XXX comment about the journal being called under
global_lock (a spin lock) in balloc.c and ialloc.c. This predates the
patch: record_global_poke already entered the journal there. It cannot
deadlock, since the journal never takes global_lock, but it should become
a mutex; I will send that separately.
-----------------------------------------------------------------------
Summary of changes:
ext2fs/balloc.c | 10 ++++++++++
ext2fs/ialloc.c | 2 ++
ext2fs/truncate.c | 25 +++++++++++++++++++------
3 files changed, 31 insertions(+), 6 deletions(-)
hooks/post-receive
--
Hurd