https://git.reactos.org/?p=reactos.git;a=commitdiff;h=34b6a287645ea80814ccd…
commit 34b6a287645ea80814ccd2aee161cf59d7acc5a0
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sun Dec 23 12:04:39 2018 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Dec 23 12:04:39 2018 +0100
[KMTESTS:CC] Add tests showing a dirty VACB isn't flushed on file growing
CORE-11819
---
.../rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c | 123 ++++++++++++++++++++-
.../rostests/kmtests/ntos_cc/CcSetFileSizes_user.c | 4 +-
2 files changed, 122 insertions(+), 5 deletions(-)
diff --git a/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c
b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c
index 7895786dd5..af644a0a18 100644
--- a/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c
+++ b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_drv.c
@@ -25,6 +25,11 @@ static PFILE_OBJECT TestFileObject;
static PDEVICE_OBJECT TestDeviceObject;
static KMT_IRP_HANDLER TestIrpHandler;
static KMT_MESSAGE_HANDLER TestMessageHandler;
+static BOOLEAN TestUnpin = FALSE;
+static BOOLEAN TestSizing = FALSE;
+static BOOLEAN TestDirtying = FALSE;
+static BOOLEAN TestUncaching = FALSE;
+static BOOLEAN TestWritten = FALSE;
NTSTATUS
TestEntry(
@@ -45,6 +50,7 @@ TestEntry(
TESTENTRY_NO_READONLY_DEVICE;
KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
+ KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
return Status;
@@ -153,6 +159,7 @@ PerformTest(
ok_eq_pointer(TestDeviceObject, NULL);
ok_eq_ulong(TestTestId, -1);
+ TestWritten = FALSE;
TestDeviceObject = DeviceObject;
TestTestId = TestId;
TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject);
@@ -171,7 +178,7 @@ PerformTest(
Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
Fcb->Header.ValidDataLength.QuadPart = VACB_MAPPING_GRANULARITY -
PAGE_SIZE;
- if (TestId > 1 && TestId < 4)
+ if ((TestId > 1 && TestId < 4) || TestId == 5)
{
Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY -
PAGE_SIZE;
}
@@ -249,6 +256,65 @@ PerformTest(
ExFreePool(Buffer);
}
}
+ else if (TestId == 4 || TestId == 5)
+ {
+ /* Kill lazy writer */
+ CcSetAdditionalCacheAttributes(TestFileObject, FALSE, TRUE);
+
+ Offset.QuadPart = 0;
+ KmtStartSeh();
+ Ret = CcPinRead(TestFileObject, &Offset, VACB_MAPPING_GRANULARITY
- PAGE_SIZE, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
+ KmtEndSeh(STATUS_SUCCESS);
+
+ if (!skip(Ret == TRUE, "CcPinRead failed\n"))
+ {
+ LARGE_INTEGER Flushed;
+
+ ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE -
sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
+ Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)) /
sizeof(ULONG)] = 0xDADADADA;
+
+ TestDirtying = TRUE;
+ CcSetDirtyPinnedData(Bcb, NULL);
+ TestDirtying = FALSE;
+
+ ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly
written!\n");
+
+ TestSizing = TRUE;
+ KmtStartSeh();
+ CcSetFileSizes(TestFileObject, &NewFileSizes);
+ KmtEndSeh(STATUS_SUCCESS);
+ TestSizing = FALSE;
+
+ ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly
written!\n");
+
+ Fcb->Header.AllocationSize.QuadPart =
VACB_MAPPING_GRANULARITY;
+ Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY;
+
+ Flushed =
CcGetFlushedValidData(TestFileObject->SectionObjectPointer, FALSE);
+ ok(Flushed.QuadPart == 0, "Flushed: %I64d\n",
Flushed.QuadPart);
+
+ TestUnpin = TRUE;
+ CcUnpinData(Bcb);
+ TestUnpin = FALSE;
+
+ ok_bool_false(TestWritten, "Dirty VACB has been unexpectedly
written!\n");
+
+ Offset.QuadPart = 0;
+ KmtStartSeh();
+ Ret = CcMapData(TestFileObject, &Offset,
VACB_MAPPING_GRANULARITY, MAP_WAIT, &Bcb, (PVOID *)&Buffer);
+ KmtEndSeh(STATUS_SUCCESS);
+
+ if (!skip(Ret == TRUE, "CcMapData failed\n"))
+ {
+ ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY - PAGE_SIZE -
sizeof(ULONG)) / sizeof(ULONG)], 0xDADADADA);
+ ok_eq_ulong(Buffer[(VACB_MAPPING_GRANULARITY -
sizeof(ULONG)) / sizeof(ULONG)], 0xBABABABA);
+
+ CcUnpinData(Bcb);
+
+ ok_bool_false(TestWritten, "Dirty VACB has been
unexpectedly written!\n");
+ }
+ }
+ }
}
}
}
@@ -271,9 +337,11 @@ CleanupTest(
{
if (CcIsFileCached(TestFileObject))
{
+ TestUncaching = TRUE;
KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent);
KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode,
FALSE, NULL);
+ TestUncaching = FALSE;
}
if (TestFileObject->FsContext != NULL)
@@ -339,7 +407,8 @@ TestIrpHandler(
PAGED_CODE();
DPRINT("IRP %x/%x\n", IoStack->MajorFunction,
IoStack->MinorFunction);
- ASSERT(IoStack->MajorFunction == IRP_MJ_READ);
+ ASSERT(IoStack->MajorFunction == IRP_MJ_READ ||
+ IoStack->MajorFunction == IRP_MJ_WRITE);
FsRtlEnterFileSystem();
@@ -350,9 +419,9 @@ TestIrpHandler(
{
PMDL Mdl;
ULONG Length;
- PVOID Buffer;
PTEST_FCB Fcb;
LARGE_INTEGER Offset;
+ PVOID Buffer, OrigBuffer;
Offset = IoStack->Parameters.Read.ByteOffset;
Length = IoStack->Parameters.Read.Length;
@@ -369,7 +438,7 @@ TestIrpHandler(
ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was
allocated!\n");
- Buffer = MapAndLockUserBuffer(Irp, Length);
+ OrigBuffer = Buffer = MapAndLockUserBuffer(Irp, Length);
ok(Buffer != NULL, "Null pointer!\n");
if (Offset.QuadPart < Fcb->Header.FileSize.QuadPart)
@@ -387,6 +456,14 @@ TestIrpHandler(
RtlFillMemory(Buffer, Length, 0xBD);
}
+ if (TestTestId == 4 && TestWritten &&
+ Offset.QuadPart <= VACB_MAPPING_GRANULARITY - PAGE_SIZE - sizeof(ULONG)
&&
+ Offset.QuadPart + Length >= VACB_MAPPING_GRANULARITY - PAGE_SIZE)
+ {
+ Buffer = (PVOID)((ULONG_PTR)OrigBuffer + (VACB_MAPPING_GRANULARITY -
PAGE_SIZE - sizeof(ULONG)));
+ RtlFillMemory(Buffer, sizeof(ULONG), 0xDA);
+ }
+
Status = STATUS_SUCCESS;
Mdl = Irp->MdlAddress;
@@ -398,6 +475,44 @@ TestIrpHandler(
Irp->IoStatus.Information = Length;
}
+ else if (IoStack->MajorFunction == IRP_MJ_WRITE)
+ {
+ PMDL Mdl;
+ ULONG Length;
+ PVOID Buffer;
+ LARGE_INTEGER Offset;
+
+ Offset = IoStack->Parameters.Write.ByteOffset;
+ Length = IoStack->Parameters.Write.Length;
+
+ ok((TestTestId == 4 || TestTestId == 5), "Unexpected test id: %d\n",
TestTestId);
+ ok_eq_pointer(DeviceObject, TestDeviceObject);
+ ok_eq_pointer(IoStack->FileObject, TestFileObject);
+
+ ok_bool_false(TestUnpin, "Write triggered while unpinning!\n");
+ ok_bool_false(TestSizing, "Write triggered while sizing!\n");
+ ok_bool_false(TestDirtying, "Write triggered while dirtying!\n");
+ ok_bool_true(TestUncaching, "Write not triggered while uncaching!\n");
+
+ ok(FlagOn(Irp->Flags, IRP_NOCACHE), "Not coming from Cc\n");
+
+ ok_irql(PASSIVE_LEVEL);
+ ok((Offset.QuadPart % PAGE_SIZE == 0 || Offset.QuadPart == 0), "Offset is
not aligned: %I64i\n", Offset.QuadPart);
+ ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
+
+ Buffer = MapAndLockUserBuffer(Irp, Length);
+ ok(Buffer != NULL, "Null pointer!\n");
+
+ Mdl = Irp->MdlAddress;
+ ok(Mdl != NULL, "Null pointer for MDL!\n");
+ ok((Mdl->MdlFlags & MDL_PAGES_LOCKED) != 0, "MDL not
locked\n");
+ ok((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) == 0, "MDL from non
paged\n");
+ ok((Irp->Flags & IRP_PAGING_IO) != 0, "Non paging IO\n");
+
+ TestWritten = TRUE;
+ Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = Length;
+ }
if (Status == STATUS_PENDING)
{
diff --git a/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c
b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c
index 121598444c..d472c5ecc9 100644
--- a/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c
+++ b/modules/rostests/kmtests/ntos_cc/CcSetFileSizes_user.c
@@ -22,8 +22,10 @@ START_TEST(CcSetFileSizes)
* 1: copy read - only FS
* 2: mapped data - FS & AS
* 3: copy read - FS & AS
+ * 4: dirty VACB - only FS
+ * 5: dirty VACB - FS & AS
*/
- for (TestId = 0; TestId < 4; ++TestId)
+ for (TestId = 0; TestId < 6; ++TestId)
{
Ret = KmtSendUlongToDriver(IOCTL_START_TEST, TestId);
ok(Ret == ERROR_SUCCESS, "KmtSendUlongToDriver failed: %lx\n", Ret);