* FILE: ntoskrnl/cc/copy.c
* PURPOSE: Implements cache managers copy interface
*
- * PROGRAMMERS:
+ * PROGRAMMERS: Some people?
+ * Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES ******************************************************************/
CcOperationZero
} CC_COPY_OPERATION;
+ULONG CcRosTraceLevel = 0;
ULONG CcFastMdlReadWait;
ULONG CcFastMdlReadNotPossible;
ULONG CcFastReadNotPossible;
ULONG CcFastReadNoWait;
ULONG CcFastReadResourceMiss;
+extern KEVENT iLazyWriterNotify;
+
/* FUNCTIONS *****************************************************************/
VOID
CcReadVirtualAddress (
PROS_VACB Vacb)
{
- ULONG Size;
+ ULONG Size, Pages;
PMDL Mdl;
NTSTATUS Status;
IO_STATUS_BLOCK IoStatus;
Size = VACB_MAPPING_GRANULARITY;
}
- Mdl = IoAllocateMdl(Vacb->BaseAddress, Size, FALSE, FALSE, NULL);
+ Pages = BYTES_TO_PAGES(Size);
+ ASSERT(Pages * PAGE_SIZE <= VACB_MAPPING_GRANULARITY);
+
+ Mdl = IoAllocateMdl(Vacb->BaseAddress, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
if (!Mdl)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
- MmBuildMdlForNonPagedPool(Mdl);
- Mdl->MdlFlags |= MDL_IO_PAGE_READ;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Status = IoPageRead(Vacb->SharedCacheMap->FileObject, Mdl, &Vacb->FileOffset, &Event, &IoStatus);
- if (Status == STATUS_PENDING)
+ Status = STATUS_SUCCESS;
+ _SEH2_TRY
+ {
+ MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
+ }
+ _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ KeBugCheck(CACHE_MANAGER);
+ } _SEH2_END;
+
+ if (NT_SUCCESS(Status))
{
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Status = IoStatus.Status;
+ Mdl->MdlFlags |= MDL_IO_PAGE_READ;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Status = IoPageRead(Vacb->SharedCacheMap->FileObject, Mdl, &Vacb->FileOffset, &Event, &IoStatus);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = IoStatus.Status;
+ }
+
+ MmUnlockPages(Mdl);
}
IoFreeMdl(Mdl);
{
return STATUS_INSUFFICIENT_RESOURCES;
}
- MmBuildMdlForNonPagedPool(Mdl);
- Mdl->MdlFlags |= MDL_IO_PAGE_READ;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Status = IoSynchronousPageWrite(Vacb->SharedCacheMap->FileObject, Mdl, &Vacb->FileOffset, &Event, &IoStatus);
- if (Status == STATUS_PENDING)
+
+ Status = STATUS_SUCCESS;
+ _SEH2_TRY
+ {
+ MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess);
+ }
+ _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ KeBugCheck(CACHE_MANAGER);
+ } _SEH2_END;
+
+ if (NT_SUCCESS(Status))
{
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Status = IoStatus.Status;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Status = IoSynchronousPageWrite(Vacb->SharedCacheMap->FileObject, Mdl, &Vacb->FileOffset, &Event, &IoStatus);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = IoStatus.Status;
+ }
+
+ MmUnlockPages(Mdl);
}
IoFreeMdl(Mdl);
if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
CurrentOffset += PartialLength;
BytesCopied += PartialLength;
- if (Buffer)
+ if (Operation != CcOperationZero)
Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
}
CurrentOffset += PartialLength;
BytesCopied += PartialLength;
- if (Buffer)
+ if (Operation != CcOperationZero)
Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
}
IoStatus->Status = STATUS_SUCCESS;
IN BOOLEAN Wait,
IN BOOLEAN Retrying)
{
- UNIMPLEMENTED;
- return FALSE;
+ PFSRTL_COMMON_FCB_HEADER Fcb;
+ PROS_SHARED_CACHE_MAP SharedCacheMap;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p BytesToWrite=%lu Wait=%d Retrying=%d\n",
+ FileObject, BytesToWrite, Wait, Retrying);
+
+ /* We cannot write if dirty pages count is above threshold */
+ if (CcTotalDirtyPages > CcDirtyPageThreshold)
+ {
+ return FALSE;
+ }
+
+ /* We cannot write if dirty pages count will bring use above
+ * XXX: Might not be accurate
+ */
+ if (CcTotalDirtyPages + (BytesToWrite / PAGE_SIZE) > CcDirtyPageThreshold)
+ {
+ return FALSE;
+ }
+
+ /* Is there a limit per file object? */
+ Fcb = FileObject->FsContext;
+ SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
+ if (!BooleanFlagOn(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES) ||
+ SharedCacheMap->DirtyPageThreshold == 0)
+ {
+ /* Nope, so that's fine, allow write operation */
+ return TRUE;
+ }
+
+ /* Is dirty page count above local threshold? */
+ if (SharedCacheMap->DirtyPages > SharedCacheMap->DirtyPageThreshold)
+ {
+ return FALSE;
+ }
+
+ /* We cannot write if dirty pages count will bring use above
+ * XXX: Might not be accurate
+ */
+ if (SharedCacheMap->DirtyPages + (BytesToWrite / PAGE_SIZE) > SharedCacheMap->DirtyPageThreshold)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
}
/*
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus)
{
+ CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d\n",
+ FileObject, FileOffset->QuadPart, Length, Wait);
+
DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
"Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
FileObject, FileOffset->QuadPart, Length, Wait,
{
IO_STATUS_BLOCK IoStatus;
+ CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d Buffer=%p\n",
+ FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
+
DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
"Length %lu, Wait %u, Buffer 0x%p)\n",
FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
}
/*
- * @unimplemented
+ * @implemented
*/
VOID
NTAPI
IN ULONG BytesToWrite,
IN BOOLEAN Retrying)
{
- UNIMPLEMENTED;
+ PROS_DEFERRED_WRITE_CONTEXT Context;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p PostRoutine=%p Context1=%p Context2=%p BytesToWrite=%lu Retrying=%d\n",
+ FileObject, PostRoutine, Context1, Context2, BytesToWrite, Retrying);
+
+ /* Try to allocate a context for queueing the write operation */
+ Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(ROS_DEFERRED_WRITE_CONTEXT), 'CcDw');
+ /* If it failed, immediately execute the operation! */
+ if (Context == NULL)
+ {
+ PostRoutine(Context1, Context2);
+ return;
+ }
+
+ /* Otherwise, initialize the context */
+ Context->FileObject = FileObject;
+ Context->PostRoutine = PostRoutine;
+ Context->Context1 = Context1;
+ Context->Context2 = Context2;
+ Context->BytesToWrite = BytesToWrite;
+ Context->Retrying = Retrying;
+
+ /* And queue it */
+ if (Retrying)
+ {
+ /* To the top, if that's a retry */
+ ExInterlockedInsertHeadList(&CcDeferredWrites,
+ &Context->CcDeferredWritesEntry,
+ &CcDeferredWriteSpinLock);
+ }
+ else
+ {
+ /* To the bottom, if that's a first time */
+ ExInterlockedInsertTailList(&CcDeferredWrites,
+ &Context->CcDeferredWritesEntry,
+ &CcDeferredWriteSpinLock);
+ }
}
/*
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus)
{
- UNIMPLEMENTED;
+ LARGE_INTEGER LargeFileOffset;
+ BOOLEAN Success;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu PageCount=%lu Buffer=%p\n",
+ FileObject, FileOffset, Length, PageCount, Buffer);
+
+ DBG_UNREFERENCED_PARAMETER(PageCount);
+
+ LargeFileOffset.QuadPart = FileOffset;
+ Success = CcCopyRead(FileObject,
+ &LargeFileOffset,
+ Length,
+ TRUE,
+ Buffer,
+ IoStatus);
+ ASSERT(Success == TRUE);
}
+
/*
* @unimplemented
*/
IN ULONG Length,
IN PVOID Buffer)
{
- UNIMPLEMENTED;
+ LARGE_INTEGER LargeFileOffset;
+ BOOLEAN Success;
+
+ CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu Buffer=%p\n",
+ FileObject, FileOffset, Length, Buffer);
+
+ LargeFileOffset.QuadPart = FileOffset;
+ Success = CcCopyWrite(FileObject,
+ &LargeFileOffset,
+ Length,
+ TRUE,
+ Buffer);
+ ASSERT(Success == TRUE);
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
CcWaitForCurrentLazyWriterActivity (
VOID)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+
+ /* Lazy writer is done when its event is set */
+ Status = KeWaitForSingleObject(&iLazyWriterNotify,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
}
/*
IO_STATUS_BLOCK Iosb;
KEVENT Event;
+ CCTRACE(CC_API_DEBUG, "FileObject=%p StartOffset=%I64u EndOffset=%I64u Wait=%d\n",
+ FileObject, StartOffset->QuadPart, EndOffset->QuadPart, Wait);
+
DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
"Wait %u)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
Wait);