[0.4.11][EXT2] Fix filesystem corruption regressions CORE-17572 CORE-17195
authorJoachim Henze <Joachim.Henze@reactos.org>
Fri, 2 Jul 2021 11:44:19 +0000 (13:44 +0200)
committerJoachim Henze <Joachim.Henze@reactos.org>
Fri, 2 Jul 2021 11:44:19 +0000 (13:44 +0200)
It regressed when we upgraded Ext2Fsd to version 0.69 from version 0.68
via CORE-13980 in 0.4.8-dev-117-g a1d7e9936d8e58bc07ff2cc73a937ce845c7d542

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 cb408102cc3e3ed853a009962482251e45861699

drivers/filesystems/ext2/src/ext3/generic.c

index 377f11f..5908586 100644 (file)
@@ -858,69 +858,62 @@ 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;
-
-    _SEH2_TRY {
-
-        while (size) {
-
-            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;
+    BOOLEAN     rc;
 
-            if (delta == 0 && len >= BLOCK_SIZE) {
-                bh = sb_getblk_zero(&Vcb->sb, block);
-            } else {
-                bh = sb_getblk(&Vcb->sb, block);
-            }
+    while (Size) {
 
-            if (!bh) {
-                DEBUG(DL_ERR, ("Ext2SaveBuffer: can't load block %I64u\n", block));
-                DbgBreak();
-                _SEH2_LEAVE;
-            }
+        PBCB        Bcb;
+        PVOID       Buffer;
+        ULONG       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;
-                   }
-            }
+        Length = (ULONG)Offset & (SIZE_256K - 1);
+        Length = SIZE_256K - Length;
+        if (Size < Length)
+            Length = Size;
 
-            _SEH2_TRY {
-                RtlCopyMemory(bh->b_data + delta, buf, len);
-                mark_buffer_dirty(bh);
-            } _SEH2_FINALLY {
-                fini_bh(&bh);
-            } _SEH2_END;
+        if ( !CcPreparePinWrite(
+                    Vcb->Volume,
+                    (PLARGE_INTEGER) (&Offset),
+                    Length,
+                    FALSE,
+                    PIN_WAIT | PIN_EXCLUSIVE,
+                    &Bcb,
+                    &Buffer )) {
 
-            buf = (PUCHAR)buf + len;
-            offset = offset + len;
-            size = size - len;
+            DEBUG(DL_ERR, ( "Ext2SaveBuffer: failed to PinLock offset %I64xh ...\n", Offset));
+            return FALSE;
         }
 
-        rc = TRUE;
+        _SEH2_TRY {
 
-    } _SEH2_FINALLY {
+            RtlCopyMemory(Buffer, Buf, Length);
+            CcSetDirtyPinnedData(Bcb, NULL );
+            SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
 
-        if (bh)
-            fini_bh(&bh);
+            rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Length);
+            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;
 }