2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/copy.c
5 * PURPOSE: Implements cache managers copy interface
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 static PFN_NUMBER CcZeroPage
= 0;
20 #define MAX_ZERO_LENGTH (256 * 1024)
22 typedef enum _CC_COPY_OPERATION
29 ULONG CcRosTraceLevel
= 0;
30 ULONG CcFastMdlReadWait
;
31 ULONG CcFastMdlReadNotPossible
;
32 ULONG CcFastReadNotPossible
;
34 ULONG CcFastReadNoWait
;
35 ULONG CcFastReadResourceMiss
;
37 /* FUNCTIONS *****************************************************************/
42 IN PFN_NUMBER PageFrameIndex
52 MI_SET_USAGE(MI_USAGE_CACHE
);
53 //MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
54 Status
= MmRequestPageMemoryConsumer(MC_SYSTEM
, TRUE
, &CcZeroPage
);
55 if (!NT_SUCCESS(Status
))
57 DbgPrint("Can't allocate CcZeroPage.\n");
58 KeBugCheck(CACHE_MANAGER
);
60 MiZeroPhysicalPage(CcZeroPage
);
65 CcReadVirtualAddress (
71 IO_STATUS_BLOCK IoStatus
;
74 Size
= (ULONG
)(Vacb
->SharedCacheMap
->SectionSize
.QuadPart
- Vacb
->FileOffset
.QuadPart
);
75 if (Size
> VACB_MAPPING_GRANULARITY
)
77 Size
= VACB_MAPPING_GRANULARITY
;
80 Pages
= BYTES_TO_PAGES(Size
);
81 ASSERT(Pages
* PAGE_SIZE
<= VACB_MAPPING_GRANULARITY
);
83 Mdl
= IoAllocateMdl(Vacb
->BaseAddress
, Pages
* PAGE_SIZE
, FALSE
, FALSE
, NULL
);
86 return STATUS_INSUFFICIENT_RESOURCES
;
89 MmBuildMdlForNonPagedPool(Mdl
);
90 Mdl
->MdlFlags
|= MDL_IO_PAGE_READ
;
91 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
92 Status
= IoPageRead(Vacb
->SharedCacheMap
->FileObject
, Mdl
, &Vacb
->FileOffset
, &Event
, &IoStatus
);
93 if (Status
== STATUS_PENDING
)
95 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
96 Status
= IoStatus
.Status
;
101 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
103 DPRINT1("IoPageRead failed, Status %x\n", Status
);
107 if (Size
< VACB_MAPPING_GRANULARITY
)
109 RtlZeroMemory((char*)Vacb
->BaseAddress
+ Size
,
110 VACB_MAPPING_GRANULARITY
- Size
);
113 return STATUS_SUCCESS
;
118 CcWriteVirtualAddress (
124 IO_STATUS_BLOCK IoStatus
;
128 Size
= (ULONG
)(Vacb
->SharedCacheMap
->SectionSize
.QuadPart
- Vacb
->FileOffset
.QuadPart
);
129 if (Size
> VACB_MAPPING_GRANULARITY
)
131 Size
= VACB_MAPPING_GRANULARITY
;
134 // Nonpaged pool PDEs in ReactOS must actually be synchronized between the
135 // MmGlobalPageDirectory and the real system PDE directory. What a mess...
141 MmGetPfnForProcess(NULL
, (PVOID
)((ULONG_PTR
)Vacb
->BaseAddress
+ (i
<< PAGE_SHIFT
)));
142 } while (++i
< (Size
>> PAGE_SHIFT
));
145 Mdl
= IoAllocateMdl(Vacb
->BaseAddress
, Size
, FALSE
, FALSE
, NULL
);
148 return STATUS_INSUFFICIENT_RESOURCES
;
150 MmBuildMdlForNonPagedPool(Mdl
);
151 Mdl
->MdlFlags
|= MDL_IO_PAGE_READ
;
152 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
153 Status
= IoSynchronousPageWrite(Vacb
->SharedCacheMap
->FileObject
, Mdl
, &Vacb
->FileOffset
, &Event
, &IoStatus
);
154 if (Status
== STATUS_PENDING
)
156 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
157 Status
= IoStatus
.Status
;
160 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
162 DPRINT1("IoPageWrite failed, Status %x\n", Status
);
167 return STATUS_SUCCESS
;
172 _Inout_ PVOID BaseAddress
,
173 _Inout_opt_ PVOID Buffer
,
175 _In_ CC_COPY_OPERATION Operation
)
177 NTSTATUS Status
= STATUS_SUCCESS
;
179 if (Operation
== CcOperationZero
)
182 RtlZeroMemory(BaseAddress
, Length
);
188 if (Operation
== CcOperationWrite
)
189 RtlCopyMemory(BaseAddress
, Buffer
, Length
);
191 RtlCopyMemory(Buffer
, BaseAddress
, Length
);
193 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
195 Status
= _SEH2_GetExceptionCode();
204 _In_ PFILE_OBJECT FileObject
,
205 _In_ LONGLONG FileOffset
,
206 _Inout_ PVOID Buffer
,
207 _In_ LONGLONG Length
,
208 _In_ CC_COPY_OPERATION Operation
,
210 _Out_ PIO_STATUS_BLOCK IoStatus
)
213 LONGLONG CurrentOffset
;
216 PROS_SHARED_CACHE_MAP SharedCacheMap
;
217 PLIST_ENTRY ListEntry
;
223 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
224 CurrentOffset
= FileOffset
;
229 /* test if the requested data is available */
230 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
231 /* FIXME: this loop doesn't take into account areas that don't have
232 * a VACB in the list yet */
233 ListEntry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
234 while (ListEntry
!= &SharedCacheMap
->CacheMapVacbListHead
)
236 Vacb
= CONTAINING_RECORD(ListEntry
,
238 CacheMapVacbListEntry
);
239 ListEntry
= ListEntry
->Flink
;
241 DoRangesIntersect(Vacb
->FileOffset
.QuadPart
,
242 VACB_MAPPING_GRANULARITY
,
243 CurrentOffset
, Length
))
245 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
246 /* data not available */
249 if (Vacb
->FileOffset
.QuadPart
>= CurrentOffset
+ Length
)
252 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
255 PartialLength
= CurrentOffset
% VACB_MAPPING_GRANULARITY
;
256 if (PartialLength
!= 0)
258 PartialLength
= min(Length
, VACB_MAPPING_GRANULARITY
- PartialLength
);
259 Status
= CcRosRequestVacb(SharedCacheMap
,
260 ROUND_DOWN(CurrentOffset
,
261 VACB_MAPPING_GRANULARITY
),
265 if (!NT_SUCCESS(Status
))
266 ExRaiseStatus(Status
);
269 Status
= CcReadVirtualAddress(Vacb
);
270 if (!NT_SUCCESS(Status
))
272 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
273 ExRaiseStatus(Status
);
276 Status
= ReadWriteOrZero((PUCHAR
)BaseAddress
+ CurrentOffset
% VACB_MAPPING_GRANULARITY
,
281 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, Operation
!= CcOperationRead
, FALSE
);
283 if (!NT_SUCCESS(Status
))
284 ExRaiseStatus(STATUS_INVALID_USER_BUFFER
);
286 Length
-= PartialLength
;
287 CurrentOffset
+= PartialLength
;
288 BytesCopied
+= PartialLength
;
290 if (Operation
!= CcOperationZero
)
291 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ PartialLength
);
296 ASSERT(CurrentOffset
% VACB_MAPPING_GRANULARITY
== 0);
297 PartialLength
= min(VACB_MAPPING_GRANULARITY
, Length
);
298 Status
= CcRosRequestVacb(SharedCacheMap
,
303 if (!NT_SUCCESS(Status
))
304 ExRaiseStatus(Status
);
306 (Operation
== CcOperationRead
||
307 PartialLength
< VACB_MAPPING_GRANULARITY
))
309 Status
= CcReadVirtualAddress(Vacb
);
310 if (!NT_SUCCESS(Status
))
312 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
313 ExRaiseStatus(Status
);
316 Status
= ReadWriteOrZero(BaseAddress
, Buffer
, PartialLength
, Operation
);
318 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, Operation
!= CcOperationRead
, FALSE
);
320 if (!NT_SUCCESS(Status
))
321 ExRaiseStatus(STATUS_INVALID_USER_BUFFER
);
323 Length
-= PartialLength
;
324 CurrentOffset
+= PartialLength
;
325 BytesCopied
+= PartialLength
;
327 if (Operation
!= CcOperationZero
)
328 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ PartialLength
);
330 IoStatus
->Status
= STATUS_SUCCESS
;
331 IoStatus
->Information
= BytesCopied
;
341 IN PFILE_OBJECT FileObject
,
342 IN ULONG BytesToWrite
,
346 CCTRACE(CC_API_DEBUG
, "FileObject=%p BytesToWrite=%lu Wait=%d Retrying=%d\n",
347 FileObject
, BytesToWrite
, Wait
, Retrying
);
358 IN PFILE_OBJECT FileObject
,
359 IN PLARGE_INTEGER FileOffset
,
363 OUT PIO_STATUS_BLOCK IoStatus
)
365 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d\n",
366 FileObject
, FileOffset
->QuadPart
, Length
, Wait
);
368 DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
369 "Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
370 FileObject
, FileOffset
->QuadPart
, Length
, Wait
,
373 return CcCopyData(FileObject
,
374 FileOffset
->QuadPart
,
388 IN PFILE_OBJECT FileObject
,
389 IN PLARGE_INTEGER FileOffset
,
394 IO_STATUS_BLOCK IoStatus
;
396 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d Buffer=%p\n",
397 FileObject
, FileOffset
->QuadPart
, Length
, Wait
, Buffer
);
399 DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
400 "Length %lu, Wait %u, Buffer 0x%p)\n",
401 FileObject
, FileOffset
->QuadPart
, Length
, Wait
, Buffer
);
403 return CcCopyData(FileObject
,
404 FileOffset
->QuadPart
,
418 IN PFILE_OBJECT FileObject
,
419 IN PCC_POST_DEFERRED_WRITE PostRoutine
,
422 IN ULONG BytesToWrite
,
425 CCTRACE(CC_API_DEBUG
, "FileObject=%p PostRoutine=%p Context1=%p Context2=%p BytesToWrite=%lu Retrying=%d\n",
426 FileObject
, PostRoutine
, Context1
, Context2
, BytesToWrite
, Retrying
);
428 PostRoutine(Context1
, Context2
);
437 IN PFILE_OBJECT FileObject
,
442 OUT PIO_STATUS_BLOCK IoStatus
)
444 LARGE_INTEGER LargeFileOffset
;
447 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%lu Length=%lu PageCount=%lu Buffer=%p\n",
448 FileObject
, FileOffset
, Length
, PageCount
, Buffer
);
450 DBG_UNREFERENCED_PARAMETER(PageCount
);
452 LargeFileOffset
.QuadPart
= FileOffset
;
453 Success
= CcCopyRead(FileObject
,
459 ASSERT(Success
== TRUE
);
468 IN PFILE_OBJECT FileObject
,
473 LARGE_INTEGER LargeFileOffset
;
476 CCTRACE(CC_API_DEBUG
, "FileObject=%p FileOffset=%lu Length=%lu Buffer=%p\n",
477 FileObject
, FileOffset
, Length
, Buffer
);
479 LargeFileOffset
.QuadPart
= FileOffset
;
480 Success
= CcCopyWrite(FileObject
,
485 ASSERT(Success
== TRUE
);
493 CcWaitForCurrentLazyWriterActivity (
497 return STATUS_NOT_IMPLEMENTED
;
506 IN PFILE_OBJECT FileObject
,
507 IN PLARGE_INTEGER StartOffset
,
508 IN PLARGE_INTEGER EndOffset
,
512 LARGE_INTEGER WriteOffset
;
517 IO_STATUS_BLOCK Iosb
;
520 CCTRACE(CC_API_DEBUG
, "FileObject=%p StartOffset=%I64u EndOffset=%I64u Wait=%d\n",
521 FileObject
, StartOffset
->QuadPart
, EndOffset
->QuadPart
, Wait
);
523 DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
524 "Wait %u)\n", FileObject
, StartOffset
->QuadPart
, EndOffset
->QuadPart
,
527 Length
= EndOffset
->QuadPart
- StartOffset
->QuadPart
;
528 WriteOffset
.QuadPart
= StartOffset
->QuadPart
;
530 if (FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
)
532 /* File is not cached */
534 Mdl
= _alloca(MmSizeOfMdl(NULL
, MAX_ZERO_LENGTH
));
538 if (Length
+ WriteOffset
.QuadPart
% PAGE_SIZE
> MAX_ZERO_LENGTH
)
540 CurrentLength
= MAX_ZERO_LENGTH
- WriteOffset
.QuadPart
% PAGE_SIZE
;
544 CurrentLength
= Length
;
546 MmInitializeMdl(Mdl
, (PVOID
)(ULONG_PTR
)WriteOffset
.QuadPart
, CurrentLength
);
547 Mdl
->MdlFlags
|= (MDL_PAGES_LOCKED
| MDL_IO_PAGE_READ
);
548 for (i
= 0; i
< ((Mdl
->Size
- sizeof(MDL
)) / sizeof(ULONG
)); i
++)
550 ((PPFN_NUMBER
)(Mdl
+ 1))[i
] = CcZeroPage
;
552 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
553 Status
= IoSynchronousPageWrite(FileObject
, Mdl
, &WriteOffset
, &Event
, &Iosb
);
554 if (Status
== STATUS_PENDING
)
556 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
557 Status
= Iosb
.Status
;
559 if (Mdl
->MdlFlags
& MDL_MAPPED_TO_SYSTEM_VA
)
561 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
563 if (!NT_SUCCESS(Status
))
567 WriteOffset
.QuadPart
+= CurrentLength
;
568 Length
-= CurrentLength
;
573 IO_STATUS_BLOCK IoStatus
;
575 return CcCopyData(FileObject
,
576 WriteOffset
.QuadPart
,