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 CcFastMdlReadWait
;
30 ULONG CcFastMdlReadNotPossible
;
31 ULONG CcFastReadNotPossible
;
33 ULONG CcFastReadNoWait
;
34 ULONG CcFastReadResourceMiss
;
36 /* FUNCTIONS *****************************************************************/
41 IN PFN_NUMBER PageFrameIndex
51 MI_SET_USAGE(MI_USAGE_CACHE
);
52 //MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
53 Status
= MmRequestPageMemoryConsumer(MC_SYSTEM
, TRUE
, &CcZeroPage
);
54 if (!NT_SUCCESS(Status
))
56 DbgPrint("Can't allocate CcZeroPage.\n");
57 KeBugCheck(CACHE_MANAGER
);
59 MiZeroPhysicalPage(CcZeroPage
);
64 CcReadVirtualAddress (
70 IO_STATUS_BLOCK IoStatus
;
73 Size
= (ULONG
)(Vacb
->SharedCacheMap
->SectionSize
.QuadPart
- Vacb
->FileOffset
.QuadPart
);
74 if (Size
> VACB_MAPPING_GRANULARITY
)
76 Size
= VACB_MAPPING_GRANULARITY
;
79 Mdl
= IoAllocateMdl(Vacb
->BaseAddress
, Size
, FALSE
, FALSE
, NULL
);
82 return STATUS_INSUFFICIENT_RESOURCES
;
85 MmBuildMdlForNonPagedPool(Mdl
);
86 Mdl
->MdlFlags
|= MDL_IO_PAGE_READ
;
87 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
88 Status
= IoPageRead(Vacb
->SharedCacheMap
->FileObject
, Mdl
, &Vacb
->FileOffset
, &Event
, &IoStatus
);
89 if (Status
== STATUS_PENDING
)
91 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
92 Status
= IoStatus
.Status
;
97 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
99 DPRINT1("IoPageRead failed, Status %x\n", Status
);
103 if (Size
< VACB_MAPPING_GRANULARITY
)
105 RtlZeroMemory((char*)Vacb
->BaseAddress
+ Size
,
106 VACB_MAPPING_GRANULARITY
- Size
);
109 return STATUS_SUCCESS
;
114 CcWriteVirtualAddress (
120 IO_STATUS_BLOCK IoStatus
;
124 Size
= (ULONG
)(Vacb
->SharedCacheMap
->SectionSize
.QuadPart
- Vacb
->FileOffset
.QuadPart
);
125 if (Size
> VACB_MAPPING_GRANULARITY
)
127 Size
= VACB_MAPPING_GRANULARITY
;
130 // Nonpaged pool PDEs in ReactOS must actually be synchronized between the
131 // MmGlobalPageDirectory and the real system PDE directory. What a mess...
137 MmGetPfnForProcess(NULL
, (PVOID
)((ULONG_PTR
)Vacb
->BaseAddress
+ (i
<< PAGE_SHIFT
)));
138 } while (++i
< (Size
>> PAGE_SHIFT
));
141 Mdl
= IoAllocateMdl(Vacb
->BaseAddress
, Size
, FALSE
, FALSE
, NULL
);
144 return STATUS_INSUFFICIENT_RESOURCES
;
146 MmBuildMdlForNonPagedPool(Mdl
);
147 Mdl
->MdlFlags
|= MDL_IO_PAGE_READ
;
148 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
149 Status
= IoSynchronousPageWrite(Vacb
->SharedCacheMap
->FileObject
, Mdl
, &Vacb
->FileOffset
, &Event
, &IoStatus
);
150 if (Status
== STATUS_PENDING
)
152 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
153 Status
= IoStatus
.Status
;
156 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
158 DPRINT1("IoPageWrite failed, Status %x\n", Status
);
163 return STATUS_SUCCESS
;
168 _Inout_ PVOID BaseAddress
,
169 _Inout_opt_ PVOID Buffer
,
171 _In_ CC_COPY_OPERATION Operation
)
173 NTSTATUS Status
= STATUS_SUCCESS
;
175 if (Operation
== CcOperationZero
)
178 RtlZeroMemory(BaseAddress
, Length
);
184 if (Operation
== CcOperationWrite
)
185 RtlCopyMemory(BaseAddress
, Buffer
, Length
);
187 RtlCopyMemory(Buffer
, BaseAddress
, Length
);
189 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
191 Status
= _SEH2_GetExceptionCode();
200 _In_ PFILE_OBJECT FileObject
,
201 _In_ LONGLONG FileOffset
,
202 _Inout_ PVOID Buffer
,
203 _In_ LONGLONG Length
,
204 _In_ CC_COPY_OPERATION Operation
,
206 _Out_ PIO_STATUS_BLOCK IoStatus
)
209 LONGLONG CurrentOffset
;
212 PROS_SHARED_CACHE_MAP SharedCacheMap
;
213 PLIST_ENTRY ListEntry
;
219 SharedCacheMap
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
220 CurrentOffset
= FileOffset
;
225 /* test if the requested data is available */
226 KeAcquireSpinLock(&SharedCacheMap
->CacheMapLock
, &OldIrql
);
227 /* FIXME: this loop doesn't take into account areas that don't have
228 * a VACB in the list yet */
229 ListEntry
= SharedCacheMap
->CacheMapVacbListHead
.Flink
;
230 while (ListEntry
!= &SharedCacheMap
->CacheMapVacbListHead
)
232 Vacb
= CONTAINING_RECORD(ListEntry
,
234 CacheMapVacbListEntry
);
235 ListEntry
= ListEntry
->Flink
;
237 DoRangesIntersect(Vacb
->FileOffset
.QuadPart
,
238 VACB_MAPPING_GRANULARITY
,
239 CurrentOffset
, Length
))
241 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
242 /* data not available */
245 if (Vacb
->FileOffset
.QuadPart
>= CurrentOffset
+ Length
)
248 KeReleaseSpinLock(&SharedCacheMap
->CacheMapLock
, OldIrql
);
251 PartialLength
= CurrentOffset
% VACB_MAPPING_GRANULARITY
;
252 if (PartialLength
!= 0)
254 PartialLength
= min(Length
, VACB_MAPPING_GRANULARITY
- PartialLength
);
255 Status
= CcRosRequestVacb(SharedCacheMap
,
256 ROUND_DOWN(CurrentOffset
,
257 VACB_MAPPING_GRANULARITY
),
261 if (!NT_SUCCESS(Status
))
262 ExRaiseStatus(Status
);
265 Status
= CcReadVirtualAddress(Vacb
);
266 if (!NT_SUCCESS(Status
))
268 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
269 ExRaiseStatus(Status
);
272 Status
= ReadWriteOrZero((PUCHAR
)BaseAddress
+ CurrentOffset
% VACB_MAPPING_GRANULARITY
,
277 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, Operation
!= CcOperationRead
, FALSE
);
279 if (!NT_SUCCESS(Status
))
280 ExRaiseStatus(STATUS_INVALID_USER_BUFFER
);
282 Length
-= PartialLength
;
283 CurrentOffset
+= PartialLength
;
284 BytesCopied
+= PartialLength
;
287 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ PartialLength
);
292 ASSERT(CurrentOffset
% VACB_MAPPING_GRANULARITY
== 0);
293 PartialLength
= min(VACB_MAPPING_GRANULARITY
, Length
);
294 Status
= CcRosRequestVacb(SharedCacheMap
,
299 if (!NT_SUCCESS(Status
))
300 ExRaiseStatus(Status
);
302 (Operation
== CcOperationRead
||
303 PartialLength
< VACB_MAPPING_GRANULARITY
))
305 Status
= CcReadVirtualAddress(Vacb
);
306 if (!NT_SUCCESS(Status
))
308 CcRosReleaseVacb(SharedCacheMap
, Vacb
, FALSE
, FALSE
, FALSE
);
309 ExRaiseStatus(Status
);
312 Status
= ReadWriteOrZero(BaseAddress
, Buffer
, PartialLength
, Operation
);
314 CcRosReleaseVacb(SharedCacheMap
, Vacb
, TRUE
, Operation
!= CcOperationRead
, FALSE
);
316 if (!NT_SUCCESS(Status
))
317 ExRaiseStatus(STATUS_INVALID_USER_BUFFER
);
319 Length
-= PartialLength
;
320 CurrentOffset
+= PartialLength
;
321 BytesCopied
+= PartialLength
;
324 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ PartialLength
);
326 IoStatus
->Status
= STATUS_SUCCESS
;
327 IoStatus
->Information
= BytesCopied
;
337 IN PFILE_OBJECT FileObject
,
338 IN ULONG BytesToWrite
,
352 IN PFILE_OBJECT FileObject
,
353 IN PLARGE_INTEGER FileOffset
,
357 OUT PIO_STATUS_BLOCK IoStatus
)
359 DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
360 "Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
361 FileObject
, FileOffset
->QuadPart
, Length
, Wait
,
364 return CcCopyData(FileObject
,
365 FileOffset
->QuadPart
,
379 IN PFILE_OBJECT FileObject
,
380 IN PLARGE_INTEGER FileOffset
,
385 IO_STATUS_BLOCK IoStatus
;
387 DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
388 "Length %lu, Wait %u, Buffer 0x%p)\n",
389 FileObject
, FileOffset
->QuadPart
, Length
, Wait
, Buffer
);
391 return CcCopyData(FileObject
,
392 FileOffset
->QuadPart
,
406 IN PFILE_OBJECT FileObject
,
407 IN PCC_POST_DEFERRED_WRITE PostRoutine
,
410 IN ULONG BytesToWrite
,
422 IN PFILE_OBJECT FileObject
,
427 OUT PIO_STATUS_BLOCK IoStatus
)
437 IN PFILE_OBJECT FileObject
,
450 CcWaitForCurrentLazyWriterActivity (
454 return STATUS_NOT_IMPLEMENTED
;
463 IN PFILE_OBJECT FileObject
,
464 IN PLARGE_INTEGER StartOffset
,
465 IN PLARGE_INTEGER EndOffset
,
469 LARGE_INTEGER WriteOffset
;
474 IO_STATUS_BLOCK Iosb
;
477 DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
478 "Wait %u)\n", FileObject
, StartOffset
->QuadPart
, EndOffset
->QuadPart
,
481 Length
= EndOffset
->QuadPart
- StartOffset
->QuadPart
;
482 WriteOffset
.QuadPart
= StartOffset
->QuadPart
;
484 if (FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
)
486 /* File is not cached */
488 Mdl
= _alloca(MmSizeOfMdl(NULL
, MAX_ZERO_LENGTH
));
492 if (Length
+ WriteOffset
.QuadPart
% PAGE_SIZE
> MAX_ZERO_LENGTH
)
494 CurrentLength
= MAX_ZERO_LENGTH
- WriteOffset
.QuadPart
% PAGE_SIZE
;
498 CurrentLength
= Length
;
500 MmInitializeMdl(Mdl
, (PVOID
)(ULONG_PTR
)WriteOffset
.QuadPart
, CurrentLength
);
501 Mdl
->MdlFlags
|= (MDL_PAGES_LOCKED
| MDL_IO_PAGE_READ
);
502 for (i
= 0; i
< ((Mdl
->Size
- sizeof(MDL
)) / sizeof(ULONG
)); i
++)
504 ((PPFN_NUMBER
)(Mdl
+ 1))[i
] = CcZeroPage
;
506 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
507 Status
= IoSynchronousPageWrite(FileObject
, Mdl
, &WriteOffset
, &Event
, &Iosb
);
508 if (Status
== STATUS_PENDING
)
510 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
511 Status
= Iosb
.Status
;
513 if (Mdl
->MdlFlags
& MDL_MAPPED_TO_SYSTEM_VA
)
515 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
517 if (!NT_SUCCESS(Status
))
521 WriteOffset
.QuadPart
+= CurrentLength
;
522 Length
-= CurrentLength
;
527 IO_STATUS_BLOCK IoStatus
;
529 return CcCopyData(FileObject
,
530 WriteOffset
.QuadPart
,