[0.4.11][EXT2] Fix filesystem corruption regressions CORE-17572 CORE-17195

It regressed when we upgraded Ext2Fsd to version 0.69 from version 0.68
via CORE-13980 in 0.4.8-dev-117-g a1d7e9936d

The fix is a partial revert of that.
Thanks to the patches author Doug Lyons.

VBox https://reactos.org/testman/compare.php?ids=77904,77908 LGTM
KVM https://reactos.org/testman/compare.php?ids=77903,77907 LGTM

fix picked from 0.4.15-dev-2792-g cb408102cc
This commit is contained in:
Joachim Henze 2021-07-02 13:44:19 +02:00
parent 22b9c6e927
commit d126fc06da

View file

@ -858,69 +858,62 @@ Ext2ZeroBuffer( IN PEXT2_IRP_CONTEXT IrpContext,
} }
#define SIZE_256K 0x40000
BOOLEAN BOOLEAN
Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT IrpContext, Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb, IN PEXT2_VCB Vcb,
IN LONGLONG offset, IN LONGLONG Offset,
IN ULONG size, IN ULONG Size,
IN PVOID buf ) IN PVOID Buf )
{ {
struct buffer_head *bh = NULL; BOOLEAN rc;
BOOLEAN rc = 0;
_SEH2_TRY { while (Size) {
while (size) { PBCB Bcb;
PVOID Buffer;
ULONG Length;
sector_t block; Length = (ULONG)Offset & (SIZE_256K - 1);
ULONG len = 0, delta = 0; Length = SIZE_256K - Length;
if (Size < Length)
Length = Size;
block = (sector_t) (offset >> BLOCK_BITS); if ( !CcPreparePinWrite(
delta = (ULONG)offset & (BLOCK_SIZE - 1); Vcb->Volume,
len = BLOCK_SIZE - delta; (PLARGE_INTEGER) (&Offset),
if (size < len) Length,
len = size; FALSE,
PIN_WAIT | PIN_EXCLUSIVE,
&Bcb,
&Buffer )) {
if (delta == 0 && len >= BLOCK_SIZE) { DEBUG(DL_ERR, ( "Ext2SaveBuffer: failed to PinLock offset %I64xh ...\n", Offset));
bh = sb_getblk_zero(&Vcb->sb, block); return FALSE;
} else {
bh = sb_getblk(&Vcb->sb, block);
}
if (!bh) {
DEBUG(DL_ERR, ("Ext2SaveBuffer: can't load block %I64u\n", block));
DbgBreak();
_SEH2_LEAVE;
}
if (!buffer_uptodate(bh)) {
int err = bh_submit_read(bh);
if (err < 0) {
DEBUG(DL_ERR, ("Ext2SaveBuffer: bh_submit_read failed: %d\n", err));
_SEH2_LEAVE;
}
}
_SEH2_TRY {
RtlCopyMemory(bh->b_data + delta, buf, len);
mark_buffer_dirty(bh);
} _SEH2_FINALLY {
fini_bh(&bh);
} _SEH2_END;
buf = (PUCHAR)buf + len;
offset = offset + len;
size = size - len;
} }
rc = TRUE; _SEH2_TRY {
} _SEH2_FINALLY { RtlCopyMemory(Buffer, Buf, Length);
CcSetDirtyPinnedData(Bcb, NULL );
SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
if (bh) rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Length);
fini_bh(&bh); if (!rc) {
DbgBreak();
Ext2Sleep(100);
rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Length);
}
} _SEH2_END; } _SEH2_FINALLY {
CcUnpinData(Bcb);
} _SEH2_END;
Buf = (PUCHAR)Buf + Length;
Offset = Offset + Length;
Size = Size - Length;
}
return rc; return rc;
} }