mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 22:18:13 +00:00
[KMTESTS:CC] Add tests showing a dirty VACB isn't flushed on file growing
CORE-11819
This commit is contained in:
parent
0917c64812
commit
34b6a28764
2 changed files with 122 additions and 5 deletions
|
@ -25,6 +25,11 @@ static PFILE_OBJECT TestFileObject;
|
||||||
static PDEVICE_OBJECT TestDeviceObject;
|
static PDEVICE_OBJECT TestDeviceObject;
|
||||||
static KMT_IRP_HANDLER TestIrpHandler;
|
static KMT_IRP_HANDLER TestIrpHandler;
|
||||||
static KMT_MESSAGE_HANDLER TestMessageHandler;
|
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
|
NTSTATUS
|
||||||
TestEntry(
|
TestEntry(
|
||||||
|
@ -45,6 +50,7 @@ TestEntry(
|
||||||
TESTENTRY_NO_READONLY_DEVICE;
|
TESTENTRY_NO_READONLY_DEVICE;
|
||||||
|
|
||||||
KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
|
KmtRegisterIrpHandler(IRP_MJ_READ, NULL, TestIrpHandler);
|
||||||
|
KmtRegisterIrpHandler(IRP_MJ_WRITE, NULL, TestIrpHandler);
|
||||||
KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
|
KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -153,6 +159,7 @@ PerformTest(
|
||||||
ok_eq_pointer(TestDeviceObject, NULL);
|
ok_eq_pointer(TestDeviceObject, NULL);
|
||||||
ok_eq_ulong(TestTestId, -1);
|
ok_eq_ulong(TestTestId, -1);
|
||||||
|
|
||||||
|
TestWritten = FALSE;
|
||||||
TestDeviceObject = DeviceObject;
|
TestDeviceObject = DeviceObject;
|
||||||
TestTestId = TestId;
|
TestTestId = TestId;
|
||||||
TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject);
|
TestFileObject = IoCreateStreamFileObject(NULL, DeviceObject);
|
||||||
|
@ -171,7 +178,7 @@ PerformTest(
|
||||||
Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
|
Fcb->Header.FileSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
|
||||||
Fcb->Header.ValidDataLength.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;
|
Fcb->Header.AllocationSize.QuadPart = VACB_MAPPING_GRANULARITY - PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -249,6 +256,65 @@ PerformTest(
|
||||||
ExFreePool(Buffer);
|
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))
|
if (CcIsFileCached(TestFileObject))
|
||||||
{
|
{
|
||||||
|
TestUncaching = TRUE;
|
||||||
KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
|
KeInitializeEvent(&CacheUninitEvent.Event, NotificationEvent, FALSE);
|
||||||
CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent);
|
CcUninitializeCacheMap(TestFileObject, &Zero, &CacheUninitEvent);
|
||||||
KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&CacheUninitEvent.Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
TestUncaching = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TestFileObject->FsContext != NULL)
|
if (TestFileObject->FsContext != NULL)
|
||||||
|
@ -339,7 +407,8 @@ TestIrpHandler(
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("IRP %x/%x\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
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();
|
FsRtlEnterFileSystem();
|
||||||
|
|
||||||
|
@ -350,9 +419,9 @@ TestIrpHandler(
|
||||||
{
|
{
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PVOID Buffer;
|
|
||||||
PTEST_FCB Fcb;
|
PTEST_FCB Fcb;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
PVOID Buffer, OrigBuffer;
|
||||||
|
|
||||||
Offset = IoStack->Parameters.Read.ByteOffset;
|
Offset = IoStack->Parameters.Read.ByteOffset;
|
||||||
Length = IoStack->Parameters.Read.Length;
|
Length = IoStack->Parameters.Read.Length;
|
||||||
|
@ -369,7 +438,7 @@ TestIrpHandler(
|
||||||
ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
|
ok(Length % PAGE_SIZE == 0, "Length is not aligned: %I64i\n", Length);
|
||||||
|
|
||||||
ok(Irp->AssociatedIrp.SystemBuffer == NULL, "A SystemBuffer was allocated!\n");
|
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");
|
ok(Buffer != NULL, "Null pointer!\n");
|
||||||
|
|
||||||
if (Offset.QuadPart < Fcb->Header.FileSize.QuadPart)
|
if (Offset.QuadPart < Fcb->Header.FileSize.QuadPart)
|
||||||
|
@ -387,6 +456,14 @@ TestIrpHandler(
|
||||||
RtlFillMemory(Buffer, Length, 0xBD);
|
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;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
Mdl = Irp->MdlAddress;
|
Mdl = Irp->MdlAddress;
|
||||||
|
@ -398,6 +475,44 @@ TestIrpHandler(
|
||||||
|
|
||||||
Irp->IoStatus.Information = Length;
|
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)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,8 +22,10 @@ START_TEST(CcSetFileSizes)
|
||||||
* 1: copy read - only FS
|
* 1: copy read - only FS
|
||||||
* 2: mapped data - FS & AS
|
* 2: mapped data - FS & AS
|
||||||
* 3: copy read - 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);
|
Ret = KmtSendUlongToDriver(IOCTL_START_TEST, TestId);
|
||||||
ok(Ret == ERROR_SUCCESS, "KmtSendUlongToDriver failed: %lx\n", Ret);
|
ok(Ret == ERROR_SUCCESS, "KmtSendUlongToDriver failed: %lx\n", Ret);
|
||||||
|
|
Loading…
Reference in a new issue