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

Reply via email to