[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
This commit is contained in:
Joachim Henze 2021-06-27 16:21:32 +02:00
parent 16e988d108
commit cb408102cc

View file

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