Applied, thanks! Milos Nikic, le mer. 07 oct. 2026 22:57:12 -0700, a ecrit: > Hello, > > This is the series I mentioned with the trunc_indirect regression fix: > it closes the window in which a freed block could be reused before the > transaction that freed it commits. > > ext2_free_blocks clears the bitmap bit at once, so the allocator can > hand a block to a new owner while the journal still holds copies of > its old contents, in the freeing transaction, in the committing one, > or in older checkpoint transactions. A home write of such a copy then > lands on the new owner's data, and a crash before the free commits > gives the block back to its old owner after it was overwritten. The > pre-notify regression was one way into this window; this series closes > the window itself. > > Patch 1 does what ext3 and ext4 do: a freed block is allocated again > only after its free commits. The bitmap and free counts still change > at free time; the block is also marked in an in-memory busy bitmap, > which ext2_new_block skips, and the commit hands the blocks back once > the old copies are marked written. Without a journal nothing changes: > freed blocks are reusable at once, as before. > > Patch 2 removes a workaround that this makes unnecessary. The orphan > list cleared i_size, i_blocks and i_block[] of an orphan inode on disk, > so that a reused block could not be reached through its block map. > That leaked the blocks of every file still open at shutdown until a > full fsck, since recovery and e2fsck saw an orphan with no blocks. > Like ext3 and ext4, the block map now stays on disk and only i_dtime > is used for the list. > > Unjournaled paths are not affected by this change. > > Known limitations, also noted as XXX comments in ext2_new_block: > > - When every free block is busy, ext2_new_block waits for the > committing transaction to hand its blocks back. The caller can > hold node locks there, such as alloc_lock, so a pager thread that > joined that transaction and waits for the same lock could deadlock > it. This needs a nearly full filesystem; I have not hit it despite > trying to! > > - When the only busy blocks belong to the caller's own transaction, > nothing can be waited for, and the caller gets ENOSPC although the > space comes back at the next commit. > > - Older transactions still in the log can hold copies of a freed > block, which a replay after a crash writes over its new owner. > That needs revoke records, which a later series adds. > > Tested on 32-bit and 64-bit Hurd images: > > - Repeated apt upgrades of an old Debian image (most of the Hurd > libraries replaced), ending with a clean halt and also with qemu > killed from the host: e2fsck clean every time. After a clean halt > e2fsck now clears the orphans of files that were still open with no > pass 5 differences, where before their blocks leaked. > > - tar -xf and rm -rf of a Linux kernel tree, with qemu killed in the > middle of each: the journal replays and e2fsck finds nothing else. > > - A 128 MB filesystem filled to ENOSPC, then 300 rounds of parallel > delete-and-rewrite plus two appenders on one file, alongside a > loop of mkdir, many small creates, chmod -R and rm -rf, with the > translator killed at random points: e2fsck clean after replay, and > every surviving copy of the reference file intact. > > - And also I ran this for the week as my daily driver on which I > develop next patches, and it is stable and working as expected. > > Milos Nikic (2): > ext2fs: Keep freed blocks busy until their free commits > ext2fs: Keep the block map of orphan inodes on disk > > ext2fs/balloc.c | 206 ++++++++++++++++++++++++++++++++++++++++------ > ext2fs/ext2fs.h | 8 ++ > ext2fs/getblk.c | 3 +- > ext2fs/inode.c | 38 +++++---- > ext2fs/journal.c | 164 ++++++++++++++++++++++++++++-------- > ext2fs/journal.h | 13 ++- > ext2fs/orphan.c | 19 ++--- > ext2fs/truncate.c | 19 ++--- > 8 files changed, 362 insertions(+), 108 deletions(-) > > -- > 2.56.0 >
-- Samuel void packerFlushTheToiletFirstThingInTheMorning( void* arg ) -+- chromium's source code -+-
