ReactOS 0.4.16-dev-401-g45b008d
copy.c
Go to the documentation of this file.
1/*
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
6 *
7 * PROGRAMMERS: Some people?
8 * Pierre Schweitzer (pierre@reactos.org)
9 */
10
11/* INCLUDES ******************************************************************/
12
13#include <ntoskrnl.h>
14#define NDEBUG
15#include <debug.h>
16
17/* GLOBALS *******************************************************************/
18
20
21#define MAX_ZERO_LENGTH (256 * 1024)
22
24{
30
38
39/* Counters:
40 * - Amount of pages flushed to the disk
41 * - Number of flush operations
42 */
45
46/* FUNCTIONS *****************************************************************/
47
48VOID
51 IN PFN_NUMBER PageFrameIndex
52);
53
54VOID
57 VOID)
58{
60
62 //MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
64 if (!NT_SUCCESS(Status))
65 {
66 DbgPrint("Can't allocate CcZeroPage.\n");
67 KeBugCheck(CACHE_MANAGER);
68 }
70}
71
72VOID
74{
75 LIST_ENTRY ToInsertBack;
76
77 InitializeListHead(&ToInsertBack);
78
79 /* We'll try to write as much as we can */
80 while (TRUE)
81 {
82 PDEFERRED_WRITE DeferredWrite;
83 PLIST_ENTRY ListEntry;
84
85 DeferredWrite = NULL;
86
88
89 if (!ListEntry)
90 break;
91
92 DeferredWrite = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks);
93
94 /* Check if we can write */
95 if (CcCanIWrite(DeferredWrite->FileObject, DeferredWrite->BytesToWrite, FALSE, RetryForceCheckPerFile))
96 {
97 /* If we have an event, set it and go along */
98 if (DeferredWrite->Event)
99 {
100 KeSetEvent(DeferredWrite->Event, IO_NO_INCREMENT, FALSE);
101 }
102 /* Otherwise, call the write routine and free the context */
103 else
104 {
105 DeferredWrite->PostRoutine(DeferredWrite->Context1, DeferredWrite->Context2);
106 ExFreePoolWithTag(DeferredWrite, 'CcDw');
107 }
108 continue;
109 }
110
111 /* Keep it for later */
112 InsertHeadList(&ToInsertBack, &DeferredWrite->DeferredWriteLinks);
113
114 /* If we don't accept modified pages, stop here */
115 if (!DeferredWrite->LimitModifiedPages)
116 {
117 break;
118 }
119 }
120
121 /* Insert what we couldn't write back in the list */
122 while (!IsListEmpty(&ToInsertBack))
123 {
124 PLIST_ENTRY ListEntry = RemoveTailList(&ToInsertBack);
126 }
127}
128
129VOID
132{
134 LONGLONG CurrentOffset;
136 PROS_SHARED_CACHE_MAP SharedCacheMap;
137 PROS_VACB Vacb;
138 ULONG PartialLength;
140 PPRIVATE_CACHE_MAP PrivateCacheMap;
143
144 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
145
146 /* Critical:
147 * PrivateCacheMap might disappear in-between if the handle
148 * to the file is closed (private is attached to the handle not to
149 * the file), so we need to lock the master lock while we deal with
150 * it. It won't disappear without attempting to lock such lock.
151 */
153 PrivateCacheMap = FileObject->PrivateCacheMap;
154 /* If the handle was closed since the read ahead was scheduled, just quit */
155 if (PrivateCacheMap == NULL)
156 {
159 return;
160 }
161 /* Otherwise, extract read offset and length and release private map */
162 else
163 {
165 CurrentOffset = PrivateCacheMap->ReadAheadOffset[1].QuadPart;
166 Length = PrivateCacheMap->ReadAheadLength[1];
168 }
170
171 /* Time to go! */
172 DPRINT("Doing ReadAhead for %p\n", FileObject);
173 /* Lock the file, first */
174 if (!SharedCacheMap->Callbacks->AcquireForReadAhead(SharedCacheMap->LazyWriteContext, FALSE))
175 {
176 Locked = FALSE;
177 goto Clear;
178 }
179
180 /* Remember it's locked */
181 Locked = TRUE;
182
183 /* Don't read past the end of the file */
184 if (CurrentOffset >= SharedCacheMap->FileSize.QuadPart)
185 {
186 goto Clear;
187 }
188 if (CurrentOffset + Length > SharedCacheMap->FileSize.QuadPart)
189 {
190 Length = SharedCacheMap->FileSize.QuadPart - CurrentOffset;
191 }
192
193 /* Next of the algorithm will lock like CcCopyData with the slight
194 * difference that we don't copy data back to an user-backed buffer
195 * We just bring data into Cc
196 */
197 PartialLength = CurrentOffset % VACB_MAPPING_GRANULARITY;
198 if (PartialLength != 0)
199 {
200 PartialLength = min(Length, VACB_MAPPING_GRANULARITY - PartialLength);
201 Status = CcRosRequestVacb(SharedCacheMap,
202 ROUND_DOWN(CurrentOffset, VACB_MAPPING_GRANULARITY),
203 &Vacb);
204 if (!NT_SUCCESS(Status))
205 {
206 DPRINT1("Failed to request VACB: %lx!\n", Status);
207 goto Clear;
208 }
209
211 {
213 CurrentOffset % VACB_MAPPING_GRANULARITY, PartialLength);
214 }
216 {
217 Success = FALSE;
218 }
220
221 if (!Success)
222 {
223 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
224 DPRINT1("Failed to read data: %lx!\n", Status);
225 goto Clear;
226 }
227
228 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
229
230 Length -= PartialLength;
231 CurrentOffset += PartialLength;
232 }
233
234 while (Length > 0)
235 {
236 ASSERT(CurrentOffset % VACB_MAPPING_GRANULARITY == 0);
237 PartialLength = min(VACB_MAPPING_GRANULARITY, Length);
238 Status = CcRosRequestVacb(SharedCacheMap,
239 CurrentOffset,
240 &Vacb);
241 if (!NT_SUCCESS(Status))
242 {
243 DPRINT1("Failed to request VACB: %lx!\n", Status);
244 goto Clear;
245 }
246
248 {
249 Success = CcRosEnsureVacbResident(Vacb, TRUE, FALSE, 0, PartialLength);
250 }
252 {
253 Success = FALSE;
254 }
256
257 if (!Success)
258 {
259 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
260 DPRINT1("Failed to read data: %lx!\n", Status);
261 goto Clear;
262 }
263
264 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
265
266 Length -= PartialLength;
267 CurrentOffset += PartialLength;
268 }
269
270Clear:
271 /* See previous comment about private cache map */
273 PrivateCacheMap = FileObject->PrivateCacheMap;
274 if (PrivateCacheMap != NULL)
275 {
276 /* Mark read ahead as unactive */
278 InterlockedAnd((volatile long *)&PrivateCacheMap->UlongFlags, ~PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE);
280 }
282
283 /* If file was locked, release it */
284 if (Locked)
285 {
286 SharedCacheMap->Callbacks->ReleaseFromReadAhead(SharedCacheMap->LazyWriteContext);
287 }
288
289 /* And drop our extra reference (See: CcScheduleReadAhead) */
291
292 return;
293}
294
295/*
296 * @unimplemented
297 */
299NTAPI
302 IN ULONG BytesToWrite,
304 IN BOOLEAN Retrying)
305{
307 KEVENT WaitEvent;
308 ULONG Length, Pages;
309 BOOLEAN PerFileDefer;
312 CC_CAN_WRITE_RETRY TryContext;
313 PROS_SHARED_CACHE_MAP SharedCacheMap;
314
315 CCTRACE(CC_API_DEBUG, "FileObject=%p BytesToWrite=%lu Wait=%d Retrying=%d\n",
316 FileObject, BytesToWrite, Wait, Retrying);
317
318 /* Write through is always OK */
320 {
321 return TRUE;
322 }
323
324 TryContext = Retrying;
325 /* Allow remote file if not from posted */
327 {
328 return TRUE;
329 }
330
331 /* Don't exceed max tolerated size */
333 if (BytesToWrite < MAX_ZERO_LENGTH)
334 {
335 Length = BytesToWrite;
336 }
337
338 Pages = BYTES_TO_PAGES(Length);
339
340 /* By default, assume limits per file won't be hit */
341 PerFileDefer = FALSE;
342 Fcb = FileObject->FsContext;
343 /* Do we have to check for limits per file? */
344 if (TryContext >= RetryForceCheckPerFile ||
346 {
347 /* If master is not locked, lock it now */
348 if (TryContext != RetryMasterLocked)
349 {
351 }
352
353 /* Let's not assume the file is cached... */
354 if (FileObject->SectionObjectPointer != NULL &&
355 FileObject->SectionObjectPointer->SharedCacheMap != NULL)
356 {
357 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
358 /* Do we have limits per file set? */
359 if (SharedCacheMap->DirtyPageThreshold != 0 &&
360 SharedCacheMap->DirtyPages != 0)
361 {
362 /* Yes, check whether they are blocking */
363 if (Pages + SharedCacheMap->DirtyPages > SharedCacheMap->DirtyPageThreshold)
364 {
365 PerFileDefer = TRUE;
366 }
367 }
368 }
369
370 /* And don't forget to release master */
371 if (TryContext != RetryMasterLocked)
372 {
374 }
375 }
376
377 /* So, now allow write if:
378 * - Not the first try or we have no throttling yet
379 * AND:
380 * - We don't exceed threshold!
381 * - We don't exceed what Mm can allow us to use
382 * + If we're above top, that's fine
383 * + If we're above bottom with limited modified pages, that's fine
384 * + Otherwise, throttle!
385 */
386 if ((TryContext != FirstTry || IsListEmpty(&CcDeferredWrites)) &&
390 !PerFileDefer)
391 {
392 return TRUE;
393 }
394
395 /* If we can wait, we'll start the wait loop for waiting till we can
396 * write for real
397 */
398 if (!Wait)
399 {
400 return FALSE;
401 }
402
403 /* Otherwise, if there are no deferred writes yet, start the lazy writer */
405 {
407
411 }
412
413 /* Initialize our wait event */
415
416 /* And prepare a dummy context */
417 Context.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
418 Context.NodeByteSize = sizeof(DEFERRED_WRITE);
419 Context.FileObject = FileObject;
420 Context.BytesToWrite = BytesToWrite;
422 Context.Event = &WaitEvent;
423
424 /* And queue it */
425 if (Retrying)
426 {
427 /* To the top, if that's a retry */
429 &Context.DeferredWriteLinks,
431 }
432 else
433 {
434 /* To the bottom, if that's a first time */
436 &Context.DeferredWriteLinks,
438 }
439
440#if DBG
441 DPRINT1("Actively deferring write for: %p\n", FileObject);
442 DPRINT1("Because:\n");
444 DPRINT1(" There are too many cache dirty pages: %x + %x >= %x\n", CcTotalDirtyPages, Pages, CcDirtyPageThreshold);
446 DPRINT1(" Available pages are below throttle top: %lx <= %lx\n", MmAvailablePages, MmThrottleTop);
447 if (MmModifiedPageListHead.Total >= 1000)
448 DPRINT1(" There are too many modified pages: %lu >= 1000\n", MmModifiedPageListHead.Total);
450 DPRINT1(" Available pages are below throttle bottom: %lx <= %lx\n", MmAvailablePages, MmThrottleBottom);
451#endif
452 /* Now, we'll loop until our event is set. When it is set, it means that caller
453 * can immediately write, and has to
454 */
455 do
456 {
459
460 return TRUE;
461}
462
463static
464int
466{
467 ULONG_PTR ExceptionAddress;
468 ULONG_PTR BeginAddress = (ULONG_PTR)Buffer;
469 ULONG_PTR EndAddress = (ULONG_PTR)Buffer + Length;
470
473 if (Except->ExceptionRecord->NumberParameters < 2)
475
476 ExceptionAddress = Except->ExceptionRecord->ExceptionInformation[1];
477 if ((ExceptionAddress >= BeginAddress) && (ExceptionAddress < EndAddress))
479
481}
482
483/*
484 * @implemented
485 */
487NTAPI
495{
496 PROS_VACB Vacb;
497 PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
499 LONGLONG CurrentOffset;
500 LONGLONG ReadEnd = FileOffset->QuadPart + Length;
501 ULONG ReadLength = 0;
502
503 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d\n",
504 FileObject, FileOffset->QuadPart, Length, Wait);
505
506 DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
507 "Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
508 FileObject, FileOffset->QuadPart, Length, Wait,
510
511 if (!SharedCacheMap)
512 return FALSE;
513
514 /* Documented to ASSERT, but KMTests test this case... */
515 // ASSERT((FileOffset->QuadPart + Length) <= SharedCacheMap->FileSize.QuadPart);
516
517 CurrentOffset = FileOffset->QuadPart;
518 while(CurrentOffset < ReadEnd)
519 {
520 Status = CcRosGetVacb(SharedCacheMap, CurrentOffset, &Vacb);
521 if (!NT_SUCCESS(Status))
522 {
524 return FALSE;
525 }
526
528 {
529 ULONG VacbOffset = CurrentOffset % VACB_MAPPING_GRANULARITY;
530 ULONG VacbLength = min(Length, VACB_MAPPING_GRANULARITY - VacbOffset);
531 SIZE_T CopyLength = VacbLength;
532
533 if (!CcRosEnsureVacbResident(Vacb, Wait, FALSE, VacbOffset, VacbLength))
534 return FALSE;
535
537 {
538 RtlCopyMemory(Buffer, (PUCHAR)Vacb->BaseAddress + VacbOffset, CopyLength);
539 }
541 {
543 }
544 _SEH2_END;
545
546 ReadLength += VacbLength;
547
548 Buffer = (PVOID)((ULONG_PTR)Buffer + VacbLength);
549 CurrentOffset += VacbLength;
550 Length -= VacbLength;
551 }
553 {
554 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
555 }
556 _SEH2_END;
557 }
558
559 IoStatus->Status = STATUS_SUCCESS;
560 IoStatus->Information = ReadLength;
561
562#if 0
563 /* If that was a successful sync read operation, let's handle read ahead */
564 if (Length == 0 && Wait)
565 {
566 PPRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap;
567
568 /* If file isn't random access and next read may get us cross VACB boundary,
569 * schedule next read
570 */
572 (CurrentOffset - 1) / VACB_MAPPING_GRANULARITY != (CurrentOffset + ReadLength - 1) / VACB_MAPPING_GRANULARITY)
573 {
575 }
576
577 /* And update read history in private cache map */
578 PrivateCacheMap->FileOffset1.QuadPart = PrivateCacheMap->FileOffset2.QuadPart;
579 PrivateCacheMap->BeyondLastByte1.QuadPart = PrivateCacheMap->BeyondLastByte2.QuadPart;
580 PrivateCacheMap->FileOffset2.QuadPart = FileOffset->QuadPart;
581 PrivateCacheMap->BeyondLastByte2.QuadPart = FileOffset->QuadPart + ReadLength;
582 }
583#endif
584
585 return TRUE;
586}
587
588/*
589 * @implemented
590 */
592NTAPI
599{
600 PROS_VACB Vacb;
601 PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
603 LONGLONG CurrentOffset;
604 LONGLONG WriteEnd;
605
606 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d Buffer=%p\n",
607 FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
608
609 DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
610 "Length %lu, Wait %u, Buffer 0x%p)\n",
611 FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
612
613 if (!SharedCacheMap)
614 return FALSE;
615
616 Status = RtlLongLongAdd(FileOffset->QuadPart, Length, &WriteEnd);
617 if (!NT_SUCCESS(Status))
619
620 ASSERT(WriteEnd <= SharedCacheMap->SectionSize.QuadPart);
621
622 CurrentOffset = FileOffset->QuadPart;
623 while(CurrentOffset < WriteEnd)
624 {
625 ULONG VacbOffset = CurrentOffset % VACB_MAPPING_GRANULARITY;
626 ULONG VacbLength = min(WriteEnd - CurrentOffset, VACB_MAPPING_GRANULARITY - VacbOffset);
627
628 Status = CcRosGetVacb(SharedCacheMap, CurrentOffset, &Vacb);
629 if (!NT_SUCCESS(Status))
630 {
632 return FALSE;
633 }
634
636 {
637 if (!CcRosEnsureVacbResident(Vacb, Wait, FALSE, VacbOffset, VacbLength))
638 {
639 return FALSE;
640 }
641
643 {
644 RtlCopyMemory((PVOID)((ULONG_PTR)Vacb->BaseAddress + VacbOffset), Buffer, VacbLength);
645 }
647 {
649 }
650 _SEH2_END;
651
652 Buffer = (PVOID)((ULONG_PTR)Buffer + VacbLength);
653 CurrentOffset += VacbLength;
654
655 /* Tell Mm */
656 Status = MmMakeSegmentDirty(FileObject->SectionObjectPointer,
657 Vacb->FileOffset.QuadPart + VacbOffset,
658 VacbLength);
659 if (!NT_SUCCESS(Status))
661 }
663 {
664 /* Do not mark the VACB as dirty if an exception was raised */
665 CcRosReleaseVacb(SharedCacheMap, Vacb, !_SEH2_AbnormalTermination(), FALSE);
666 }
667 _SEH2_END;
668 }
669
670 /* Flush if needed */
671 if (FileObject->Flags & FO_WRITE_THROUGH)
672 CcFlushCache(FileObject->SectionObjectPointer, FileOffset, Length, NULL);
673
674 return TRUE;
675}
676
677/*
678 * @implemented
679 */
680VOID
681NTAPI
684 IN PCC_POST_DEFERRED_WRITE PostRoutine,
687 IN ULONG BytesToWrite,
688 IN BOOLEAN Retrying)
689{
693
694 CCTRACE(CC_API_DEBUG, "FileObject=%p PostRoutine=%p Context1=%p Context2=%p BytesToWrite=%lu Retrying=%d\n",
695 FileObject, PostRoutine, Context1, Context2, BytesToWrite, Retrying);
696
697 /* Try to allocate a context for queueing the write operation */
699 /* If it failed, immediately execute the operation! */
700 if (Context == NULL)
701 {
702 PostRoutine(Context1, Context2);
703 return;
704 }
705
706 Fcb = FileObject->FsContext;
707
708 /* Otherwise, initialize the context */
710 Context->NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
711 Context->NodeByteSize = sizeof(DEFERRED_WRITE);
712 Context->FileObject = FileObject;
713 Context->PostRoutine = PostRoutine;
714 Context->Context1 = Context1;
715 Context->Context2 = Context2;
716 Context->BytesToWrite = BytesToWrite;
718
719 /* And queue it */
720 if (Retrying)
721 {
722 /* To the top, if that's a retry */
724 &Context->DeferredWriteLinks,
726 }
727 else
728 {
729 /* To the bottom, if that's a first time */
731 &Context->DeferredWriteLinks,
733 }
734
735 /* Try to execute the posted writes */
737
738 /* Schedule a lazy writer run to handle deferred writes */
741 {
743 }
745}
746
747/*
748 * @unimplemented
749 */
750VOID
751NTAPI
756 IN ULONG PageCount,
759{
760 LARGE_INTEGER LargeFileOffset;
762
763 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu PageCount=%lu Buffer=%p\n",
764 FileObject, FileOffset, Length, PageCount, Buffer);
765
767
768 LargeFileOffset.QuadPart = FileOffset;
770 &LargeFileOffset,
771 Length,
772 TRUE,
773 Buffer,
774 IoStatus);
775 ASSERT(Success == TRUE);
776}
777
778/*
779 * @unimplemented
780 */
781VOID
782NTAPI
788{
789 LARGE_INTEGER LargeFileOffset;
791
792 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu Buffer=%p\n",
794
795 LargeFileOffset.QuadPart = FileOffset;
797 &LargeFileOffset,
798 Length,
799 TRUE,
800 Buffer);
801 ASSERT(Success == TRUE);
802}
803
804/*
805 * @implemented
806 */
808NTAPI
811 IN PLARGE_INTEGER StartOffset,
812 IN PLARGE_INTEGER EndOffset,
814{
818 PROS_VACB Vacb;
819 PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
820
821 CCTRACE(CC_API_DEBUG, "FileObject=%p StartOffset=%I64u EndOffset=%I64u Wait=%d\n",
822 FileObject, StartOffset->QuadPart, EndOffset->QuadPart, Wait);
823
824 DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
825 "Wait %u)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
826 Wait);
827
828 Length = EndOffset->QuadPart - StartOffset->QuadPart;
829 WriteOffset.QuadPart = StartOffset->QuadPart;
830
831 if (!SharedCacheMap)
832 {
833 /* Make this a non-cached write */
836 PMDL Mdl;
837 ULONG i;
838 ULONG CurrentLength;
839 PPFN_NUMBER PfnArray;
840
841 /* Setup our Mdl */
843 if (!Mdl)
845
846 PfnArray = MmGetMdlPfnArray(Mdl);
847 for (i = 0; i < BYTES_TO_PAGES(Mdl->ByteCount); i++)
848 PfnArray[i] = CcZeroPage;
849 Mdl->MdlFlags |= MDL_PAGES_LOCKED;
850
851 /* Perform the write sequencially */
852 while (Length > 0)
853 {
854 CurrentLength = min(Length, MAX_ZERO_LENGTH);
855
856 Mdl->ByteCount = CurrentLength;
857
860 if (Status == STATUS_PENDING)
861 {
863 Status = Iosb.Status;
864 }
865 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
866 {
867 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
868 }
869 if (!NT_SUCCESS(Status))
870 {
871 IoFreeMdl(Mdl);
873 }
874 WriteOffset.QuadPart += CurrentLength;
875 Length -= CurrentLength;
876 }
877
878 IoFreeMdl(Mdl);
879
880 return TRUE;
881 }
882
883 /* See if we should simply truncate the valid data length */
884 if ((StartOffset->QuadPart < SharedCacheMap->ValidDataLength.QuadPart) && (EndOffset->QuadPart >= SharedCacheMap->ValidDataLength.QuadPart))
885 {
886 DPRINT1("Truncating VDL.\n");
887 SharedCacheMap->ValidDataLength = *StartOffset;
888 return TRUE;
889 }
890
891 ASSERT(EndOffset->QuadPart <= SharedCacheMap->SectionSize.QuadPart);
892
893 while(WriteOffset.QuadPart < EndOffset->QuadPart)
894 {
895 ULONG VacbOffset = WriteOffset.QuadPart % VACB_MAPPING_GRANULARITY;
896 ULONG VacbLength = min(Length, VACB_MAPPING_GRANULARITY - VacbOffset);
897
898 Status = CcRosGetVacb(SharedCacheMap, WriteOffset.QuadPart, &Vacb);
899 if (!NT_SUCCESS(Status))
900 {
902 return FALSE;
903 }
904
906 {
907 if (!CcRosEnsureVacbResident(Vacb, Wait, FALSE, VacbOffset, VacbLength))
908 {
909 return FALSE;
910 }
911
912 RtlZeroMemory((PVOID)((ULONG_PTR)Vacb->BaseAddress + VacbOffset), VacbLength);
913
914 WriteOffset.QuadPart += VacbLength;
915 Length -= VacbLength;
916
917 /* Tell Mm */
918 Status = MmMakeSegmentDirty(FileObject->SectionObjectPointer,
919 Vacb->FileOffset.QuadPart + VacbOffset,
920 VacbLength);
921 if (!NT_SUCCESS(Status))
923 }
925 {
926 /* Do not mark the VACB as dirty if an exception was raised */
927 CcRosReleaseVacb(SharedCacheMap, Vacb, !_SEH2_AbnormalTermination(), FALSE);
928 }
929 _SEH2_END;
930 }
931
932 /* Flush if needed */
933 if (FileObject->Flags & FO_WRITE_THROUGH)
934 CcFlushCache(FileObject->SectionObjectPointer, StartOffset, EndOffset->QuadPart - StartOffset->QuadPart, NULL);
935
936 return TRUE;
937}
ULONG ReadLength
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
VOID NTAPI CcScheduleReadAhead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length)
Definition: cachesub.c:92
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB Fcb
Definition: cdprocs.h:159
Definition: bufpool.h:45
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
return Iosb
Definition: create.c:4402
#define ULONG_PTR
Definition: config.h:101
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
@ Success
Definition: eventcreate.c:712
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FSRTL_FLAG_LIMIT_MODIFIED_PAGES
Definition: fsrtltypes.h:47
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define DbgPrint
Definition: hal.h:12
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
PLIST_ENTRY NTAPI ExInterlockedInsertHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:114
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
PLIST_ENTRY NTAPI ExInterlockedRemoveHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:166
#define InterlockedAnd
Definition: interlocked.h:62
NTSTATUS NTAPI IoSynchronousPageWrite(IN PFILE_OBJECT FileObject, IN PMDL Mdl, IN PLARGE_INTEGER Offset, IN PKEVENT Event, IN PIO_STATUS_BLOCK StatusBlock)
Definition: iofunc.c:1146
LARGE_INTEGER CcIdleDelay
Definition: lazywrite.c:46
VOID CcScheduleLazyWriteScan(IN BOOLEAN NoDelay)
Definition: lazywrite.c:210
LAZY_WRITER LazyWriter
Definition: lazywrite.c:37
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:837
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static void Clear(void)
Definition: treeview.c:388
#define min(a, b)
Definition: monoChain.cc:55
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE
Definition: cctypes.h:64
struct _DEFERRED_WRITE DEFERRED_WRITE
#define KernelMode
Definition: asm.h:38
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:326
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
VOID NTAPI CcFastCopyWrite(IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN PVOID Buffer)
Definition: copy.c:783
ULONG CcFastMdlReadNotPossible
Definition: copy.c:33
ULONG CcFastReadResourceMiss
Definition: copy.c:37
VOID CcPostDeferredWrites(VOID)
Definition: copy.c:73
static int CcpCheckInvalidUserBuffer(PEXCEPTION_POINTERS Except, PVOID Buffer, ULONG Length)
Definition: copy.c:465
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copy.c:593
static PFN_NUMBER CcZeroPage
Definition: copy.c:19
VOID NTAPI CcInitCacheZeroPage(VOID)
Definition: copy.c:56
ULONG CcFastReadNoWait
Definition: copy.c:36
VOID CcPerformReadAhead(IN PFILE_OBJECT FileObject)
Definition: copy.c:130
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN BOOLEAN Retrying)
Definition: copy.c:300
ULONG CcDataPages
Definition: copy.c:43
BOOLEAN NTAPI CcCopyRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus)
Definition: copy.c:488
BOOLEAN NTAPI CcZeroData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait)
Definition: copy.c:809
ULONG CcDataFlushes
Definition: copy.c:44
_CC_CAN_WRITE_RETRY
Definition: copy.c:24
@ RetryForceCheckPerFile
Definition: copy.c:27
@ FirstTry
Definition: copy.c:25
@ RetryAllowRemote
Definition: copy.c:26
@ RetryMasterLocked
Definition: copy.c:28
ULONG CcFastReadNotPossible
Definition: copy.c:34
ULONG CcRosTraceLevel
Definition: copy.c:31
ULONG CcFastMdlReadWait
Definition: copy.c:32
enum _CC_CAN_WRITE_RETRY CC_CAN_WRITE_RETRY
#define MAX_ZERO_LENGTH
Definition: copy.c:21
VOID NTAPI CcFastCopyRead(IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN ULONG PageCount, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus)
Definition: copy.c:752
ULONG CcFastReadWait
Definition: copy.c:35
VOID NTAPI CcDeferWrite(IN PFILE_OBJECT FileObject, IN PCC_POST_DEFERRED_WRITE PostRoutine, IN PVOID Context1, IN PVOID Context2, IN ULONG BytesToWrite, IN BOOLEAN Retrying)
Definition: copy.c:682
KSPIN_LOCK CcDeferredWriteSpinLock
Definition: view.c:58
NTSTATUS CcRosReleaseVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, PROS_VACB Vacb, BOOLEAN Dirty, BOOLEAN Mapped)
Definition: view.c:591
NTSTATUS CcRosRequestVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:1028
LIST_ENTRY CcDeferredWrites
Definition: view.c:57
BOOLEAN CcRosEnsureVacbResident(_In_ PROS_VACB Vacb, _In_ BOOLEAN Wait, _In_ BOOLEAN NoRead, _In_ ULONG Offset, _In_ ULONG Length)
Definition: view.c:931
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:977
ULONG CcDirtyPageThreshold
Definition: view.c:55
ULONG CcTotalDirtyPages
Definition: view.c:56
#define NODE_TYPE_DEFERRED_WRITE
Definition: cc.h:287
#define CC_API_DEBUG
Definition: cc.h:11
#define CCTRACE(x, fmt,...)
Definition: cc.h:36
@ MI_USAGE_CACHE
Definition: mm.h:342
NTSTATUS NTAPI MmMakeSegmentDirty(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_ LONGLONG Offset, _In_ ULONG Length)
Definition: section.c:4994
ULONG MmThrottleTop
Definition: mminit.c:396
#define MC_SYSTEM
Definition: mm.h:115
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
#define MI_SET_USAGE(x)
Definition: mm.h:317
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:313
ULONG MmThrottleBottom
Definition: mminit.c:397
#define ExRaiseStatus
Definition: ntoskrnl.h:114
BOOLEAN NTAPI IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)
Definition: file.c:3278
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
ULONG * PPFN_NUMBER
Definition: ke.h:9
ULONG PFN_NUMBER
Definition: ke.h:9
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PACQUIRE_FOR_READ_AHEAD AcquireForReadAhead
Definition: cctypes.h:41
PRELEASE_FROM_READ_AHEAD ReleaseFromReadAhead
Definition: cctypes.h:42
PCC_POST_DEFERRED_WRITE PostRoutine
Definition: cctypes.h:175
PKEVENT Event
Definition: cctypes.h:174
ULONG BytesToWrite
Definition: cctypes.h:172
BOOLEAN LimitModifiedPages
Definition: cctypes.h:178
PVOID Context1
Definition: cctypes.h:176
PFILE_OBJECT FileObject
Definition: cctypes.h:171
PVOID Context2
Definition: cctypes.h:177
LIST_ENTRY DeferredWriteLinks
Definition: cctypes.h:173
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
DWORD ExceptionCode
Definition: compat.h:208
DWORD NumberParameters
Definition: compat.h:212
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
ULONG Flags
Definition: ntfs.h:536
BOOLEAN ScanActive
Definition: cc.h:247
Definition: typedefs.h:120
PFN_NUMBER Total
Definition: mm.h:443
LARGE_INTEGER BeyondLastByte1
Definition: cctypes.h:78
LARGE_INTEGER FileOffset2
Definition: cctypes.h:79
LARGE_INTEGER FileOffset1
Definition: cctypes.h:77
ULONG ReadAheadLength[2]
Definition: cctypes.h:82
LARGE_INTEGER ReadAheadOffset[2]
Definition: cctypes.h:81
KSPIN_LOCK ReadAheadSpinLock
Definition: cctypes.h:83
ULONG UlongFlags
Definition: cctypes.h:73
LARGE_INTEGER BeyondLastByte2
Definition: cctypes.h:80
LARGE_INTEGER FileSize
Definition: cc.h:175
LARGE_INTEGER ValidDataLength
Definition: cc.h:178
PCACHE_MANAGER_CALLBACKS Callbacks
Definition: cc.h:185
ULONG DirtyPageThreshold
Definition: cc.h:188
PVOID LazyWriteContext
Definition: cc.h:186
ULONG DirtyPages
Definition: cc.h:180
LARGE_INTEGER SectionSize
Definition: cc.h:177
Definition: cc.h:208
LARGE_INTEGER FileOffset
Definition: cc.h:223
PVOID BaseAddress
Definition: cc.h:210
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT Context1
Definition: tdikrnl.h:1095
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT _In_ PTDI_PNP_CONTEXT Context2
Definition: tdikrnl.h:1096
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET WriteOffset
Definition: wdfusb.h:1921
#define VACB_MAPPING_GRANULARITY
VOID(NTAPI * PCC_POST_DEFERRED_WRITE)(_In_ PVOID Context1, _In_ PVOID Context2)
Definition: cctypes.h:66
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define FO_WRITE_THROUGH
Definition: iotypes.h:1779
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
* PFILE_OBJECT
Definition: iotypes.h:1998
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
@ LockQueueMasterLock
Definition: ketypes.h:663
#define BYTES_TO_PAGES(Size)
#define MmGetMdlPfnArray(_Mdl)
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
#define ObDereferenceObject
Definition: obfuncs.h:203