ReactOS  0.4.15-dev-3291-gea4c1a0
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 
23 typedef enum _CC_CAN_WRITE_RETRY
24 {
25  FirstTry = 0,
30 
38 
39 /* Counters:
40  * - Amount of pages flushed to the disk
41  * - Number of flush operations
42  */
45 
46 /* FUNCTIONS *****************************************************************/
47 
48 VOID
49 NTAPI
51  IN PFN_NUMBER PageFrameIndex
52 );
53 
54 VOID
55 NTAPI
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 
72 VOID
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 
129 VOID
132 {
134  LONGLONG CurrentOffset;
135  KIRQL OldIrql;
136  PROS_SHARED_CACHE_MAP SharedCacheMap;
137  PROS_VACB Vacb;
138  ULONG PartialLength;
139  ULONG Length;
140  PPRIVATE_CACHE_MAP PrivateCacheMap;
141  BOOLEAN Locked;
142 
143  SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
144 
145  /* Critical:
146  * PrivateCacheMap might disappear in-between if the handle
147  * to the file is closed (private is attached to the handle not to
148  * the file), so we need to lock the master lock while we deal with
149  * it. It won't disappear without attempting to lock such lock.
150  */
152  PrivateCacheMap = FileObject->PrivateCacheMap;
153  /* If the handle was closed since the read ahead was scheduled, just quit */
154  if (PrivateCacheMap == NULL)
155  {
158  return;
159  }
160  /* Otherwise, extract read offset and length and release private map */
161  else
162  {
164  CurrentOffset = PrivateCacheMap->ReadAheadOffset[1].QuadPart;
165  Length = PrivateCacheMap->ReadAheadLength[1];
167  }
169 
170  /* Time to go! */
171  DPRINT("Doing ReadAhead for %p\n", FileObject);
172  /* Lock the file, first */
173  if (!SharedCacheMap->Callbacks->AcquireForReadAhead(SharedCacheMap->LazyWriteContext, FALSE))
174  {
175  Locked = FALSE;
176  goto Clear;
177  }
178 
179  /* Remember it's locked */
180  Locked = TRUE;
181 
182  /* Don't read past the end of the file */
183  if (CurrentOffset >= SharedCacheMap->FileSize.QuadPart)
184  {
185  goto Clear;
186  }
187  if (CurrentOffset + Length > SharedCacheMap->FileSize.QuadPart)
188  {
189  Length = SharedCacheMap->FileSize.QuadPart - CurrentOffset;
190  }
191 
192  /* Next of the algorithm will lock like CcCopyData with the slight
193  * difference that we don't copy data back to an user-backed buffer
194  * We just bring data into Cc
195  */
196  PartialLength = CurrentOffset % VACB_MAPPING_GRANULARITY;
197  if (PartialLength != 0)
198  {
199  PartialLength = min(Length, VACB_MAPPING_GRANULARITY - PartialLength);
200  Status = CcRosRequestVacb(SharedCacheMap,
201  ROUND_DOWN(CurrentOffset, VACB_MAPPING_GRANULARITY),
202  &Vacb);
203  if (!NT_SUCCESS(Status))
204  {
205  DPRINT1("Failed to request VACB: %lx!\n", Status);
206  goto Clear;
207  }
208 
210  CurrentOffset % VACB_MAPPING_GRANULARITY, PartialLength);
211  if (!NT_SUCCESS(Status))
212  {
213  CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
214  DPRINT1("Failed to read data: %lx!\n", Status);
215  goto Clear;
216  }
217 
218  CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
219 
220  Length -= PartialLength;
221  CurrentOffset += PartialLength;
222  }
223 
224  while (Length > 0)
225  {
226  ASSERT(CurrentOffset % VACB_MAPPING_GRANULARITY == 0);
227  PartialLength = min(VACB_MAPPING_GRANULARITY, Length);
228  Status = CcRosRequestVacb(SharedCacheMap,
229  CurrentOffset,
230  &Vacb);
231  if (!NT_SUCCESS(Status))
232  {
233  DPRINT1("Failed to request VACB: %lx!\n", Status);
234  goto Clear;
235  }
236 
237  Status = CcRosEnsureVacbResident(Vacb, TRUE, FALSE, 0, PartialLength);
238  if (!NT_SUCCESS(Status))
239  {
240  CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
241  DPRINT1("Failed to read data: %lx!\n", Status);
242  goto Clear;
243  }
244 
245  CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
246 
247  Length -= PartialLength;
248  CurrentOffset += PartialLength;
249  }
250 
251 Clear:
252  /* See previous comment about private cache map */
254  PrivateCacheMap = FileObject->PrivateCacheMap;
255  if (PrivateCacheMap != NULL)
256  {
257  /* Mark read ahead as unactive */
259  InterlockedAnd((volatile long *)&PrivateCacheMap->UlongFlags, ~PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE);
261  }
263 
264  /* If file was locked, release it */
265  if (Locked)
266  {
267  SharedCacheMap->Callbacks->ReleaseFromReadAhead(SharedCacheMap->LazyWriteContext);
268  }
269 
270  /* And drop our extra reference (See: CcScheduleReadAhead) */
272 
273  return;
274 }
275 
276 /*
277  * @unimplemented
278  */
279 BOOLEAN
280 NTAPI
283  IN ULONG BytesToWrite,
284  IN BOOLEAN Wait,
285  IN BOOLEAN Retrying)
286 {
287  KIRQL OldIrql;
288  KEVENT WaitEvent;
289  ULONG Length, Pages;
290  BOOLEAN PerFileDefer;
293  CC_CAN_WRITE_RETRY TryContext;
294  PROS_SHARED_CACHE_MAP SharedCacheMap;
295 
296  CCTRACE(CC_API_DEBUG, "FileObject=%p BytesToWrite=%lu Wait=%d Retrying=%d\n",
297  FileObject, BytesToWrite, Wait, Retrying);
298 
299  /* Write through is always OK */
301  {
302  return TRUE;
303  }
304 
305  TryContext = Retrying;
306  /* Allow remote file if not from posted */
307  if (IoIsFileOriginRemote(FileObject) && TryContext < RetryAllowRemote)
308  {
309  return TRUE;
310  }
311 
312  /* Don't exceed max tolerated size */
314  if (BytesToWrite < MAX_ZERO_LENGTH)
315  {
316  Length = BytesToWrite;
317  }
318 
319  Pages = BYTES_TO_PAGES(Length);
320 
321  /* By default, assume limits per file won't be hit */
322  PerFileDefer = FALSE;
323  Fcb = FileObject->FsContext;
324  /* Do we have to check for limits per file? */
325  if (TryContext >= RetryForceCheckPerFile ||
327  {
328  /* If master is not locked, lock it now */
329  if (TryContext != RetryMasterLocked)
330  {
332  }
333 
334  /* Let's not assume the file is cached... */
335  if (FileObject->SectionObjectPointer != NULL &&
336  FileObject->SectionObjectPointer->SharedCacheMap != NULL)
337  {
338  SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
339  /* Do we have limits per file set? */
340  if (SharedCacheMap->DirtyPageThreshold != 0 &&
341  SharedCacheMap->DirtyPages != 0)
342  {
343  /* Yes, check whether they are blocking */
344  if (Pages + SharedCacheMap->DirtyPages > SharedCacheMap->DirtyPageThreshold)
345  {
346  PerFileDefer = TRUE;
347  }
348  }
349  }
350 
351  /* And don't forget to release master */
352  if (TryContext != RetryMasterLocked)
353  {
355  }
356  }
357 
358  /* So, now allow write if:
359  * - Not the first try or we have no throttling yet
360  * AND:
361  * - We don't exceed threshold!
362  * - We don't exceed what Mm can allow us to use
363  * + If we're above top, that's fine
364  * + If we're above bottom with limited modified pages, that's fine
365  * + Otherwise, throttle!
366  */
367  if ((TryContext != FirstTry || IsListEmpty(&CcDeferredWrites)) &&
371  !PerFileDefer)
372  {
373  return TRUE;
374  }
375 
376  /* If we can wait, we'll start the wait loop for waiting till we can
377  * write for real
378  */
379  if (!Wait)
380  {
381  return FALSE;
382  }
383 
384  /* Initialize our wait event */
386 
387  /* And prepare a dummy context */
388  Context.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
389  Context.NodeByteSize = sizeof(DEFERRED_WRITE);
390  Context.FileObject = FileObject;
391  Context.BytesToWrite = BytesToWrite;
393  Context.Event = &WaitEvent;
394 
395  /* And queue it */
396  if (Retrying)
397  {
398  /* To the top, if that's a retry */
400  &Context.DeferredWriteLinks,
402  }
403  else
404  {
405  /* To the bottom, if that's a first time */
407  &Context.DeferredWriteLinks,
409  }
410 
411  /* Now make sure that the lazy scan writer will be active */
413  if (!LazyWriter.ScanActive)
416 
417 #if DBG
418  DPRINT1("Actively deferring write for: %p\n", FileObject);
419  DPRINT1("Because:\n");
421  DPRINT1(" There are too many cache dirty pages: %x + %x >= %x\n", CcTotalDirtyPages, Pages, CcDirtyPageThreshold);
423  DPRINT1(" Available pages are below throttle top: %lx <= %lx\n", MmAvailablePages, MmThrottleTop);
424  if (MmModifiedPageListHead.Total >= 1000)
425  DPRINT1(" There are too many modified pages: %lu >= 1000\n", MmModifiedPageListHead.Total);
427  DPRINT1(" Available pages are below throttle bottom: %lx <= %lx\n", MmAvailablePages, MmThrottleBottom);
428 #endif
429  /* Now, we'll loop until our event is set. When it is set, it means that caller
430  * can immediately write, and has to
431  */
432  do
433  {
436 
437  return TRUE;
438 }
439 
440 static
441 int
443 {
444  ULONG_PTR ExceptionAddress;
445  ULONG_PTR BeginAddress = (ULONG_PTR)Buffer;
446  ULONG_PTR EndAddress = (ULONG_PTR)Buffer + Length;
447 
450  if (Except->ExceptionRecord->NumberParameters < 2)
452 
453  ExceptionAddress = Except->ExceptionRecord->ExceptionInformation[1];
454  if ((ExceptionAddress >= BeginAddress) && (ExceptionAddress < EndAddress))
456 
458 }
459 
460 /*
461  * @implemented
462  */
463 BOOLEAN
464 NTAPI
468  IN ULONG Length,
469  IN BOOLEAN Wait,
470  OUT PVOID Buffer,
472 {
473  PROS_VACB Vacb;
474  PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
476  LONGLONG CurrentOffset;
477  LONGLONG ReadEnd = FileOffset->QuadPart + Length;
478  ULONG ReadLength = 0;
479 
480  CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d\n",
481  FileObject, FileOffset->QuadPart, Length, Wait);
482 
483  DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
484  "Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
485  FileObject, FileOffset->QuadPart, Length, Wait,
486  Buffer, IoStatus);
487 
488  if (!SharedCacheMap)
489  return FALSE;
490 
491  /* Documented to ASSERT, but KMTests test this case... */
492  // ASSERT((FileOffset->QuadPart + Length) <= SharedCacheMap->FileSize.QuadPart);
493 
494  CurrentOffset = FileOffset->QuadPart;
495  while(CurrentOffset < ReadEnd)
496  {
497  Status = CcRosGetVacb(SharedCacheMap, CurrentOffset, &Vacb);
498  if (!NT_SUCCESS(Status))
499  {
501  return FALSE;
502  }
503 
504  _SEH2_TRY
505  {
506  ULONG VacbOffset = CurrentOffset % VACB_MAPPING_GRANULARITY;
507  ULONG VacbLength = min(Length, VACB_MAPPING_GRANULARITY - VacbOffset);
508  SIZE_T CopyLength = VacbLength;
509 
510  if (!CcRosEnsureVacbResident(Vacb, Wait, FALSE, VacbOffset, VacbLength))
511  return FALSE;
512 
513  _SEH2_TRY
514  {
515  RtlCopyMemory(Buffer, (PUCHAR)Vacb->BaseAddress + VacbOffset, CopyLength);
516  }
518  {
520  }
521  _SEH2_END;
522 
523  ReadLength += VacbLength;
524 
525  Buffer = (PVOID)((ULONG_PTR)Buffer + VacbLength);
526  CurrentOffset += VacbLength;
527  Length -= VacbLength;
528  }
530  {
531  CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
532  }
533  _SEH2_END;
534  }
535 
536  IoStatus->Status = STATUS_SUCCESS;
537  IoStatus->Information = ReadLength;
538 
539 #if 0
540  /* If that was a successful sync read operation, let's handle read ahead */
541  if (Length == 0 && Wait)
542  {
543  PPRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap;
544 
545  /* If file isn't random access and next read may get us cross VACB boundary,
546  * schedule next read
547  */
548  if (!BooleanFlagOn(FileObject->Flags, FO_RANDOM_ACCESS) &&
549  (CurrentOffset - 1) / VACB_MAPPING_GRANULARITY != (CurrentOffset + ReadLength - 1) / VACB_MAPPING_GRANULARITY)
550  {
552  }
553 
554  /* And update read history in private cache map */
555  PrivateCacheMap->FileOffset1.QuadPart = PrivateCacheMap->FileOffset2.QuadPart;
556  PrivateCacheMap->BeyondLastByte1.QuadPart = PrivateCacheMap->BeyondLastByte2.QuadPart;
557  PrivateCacheMap->FileOffset2.QuadPart = FileOffset->QuadPart;
558  PrivateCacheMap->BeyondLastByte2.QuadPart = FileOffset->QuadPart + ReadLength;
559  }
560 #endif
561 
562  return TRUE;
563 }
564 
565 /*
566  * @implemented
567  */
568 BOOLEAN
569 NTAPI
573  IN ULONG Length,
574  IN BOOLEAN Wait,
575  IN PVOID Buffer)
576 {
577  PROS_VACB Vacb;
578  PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
580  LONGLONG CurrentOffset;
581  LONGLONG WriteEnd;
582 
583  CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%I64d Length=%lu Wait=%d Buffer=%p\n",
584  FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
585 
586  DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
587  "Length %lu, Wait %u, Buffer 0x%p)\n",
588  FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
589 
590  if (!SharedCacheMap)
591  return FALSE;
592 
593  Status = RtlLongLongAdd(FileOffset->QuadPart, Length, &WriteEnd);
594  if (!NT_SUCCESS(Status))
596 
597  ASSERT(WriteEnd <= SharedCacheMap->SectionSize.QuadPart);
598 
599  CurrentOffset = FileOffset->QuadPart;
600  while(CurrentOffset < WriteEnd)
601  {
602  ULONG VacbOffset = CurrentOffset % VACB_MAPPING_GRANULARITY;
603  ULONG VacbLength = min(WriteEnd - CurrentOffset, VACB_MAPPING_GRANULARITY - VacbOffset);
604 
605  Status = CcRosGetVacb(SharedCacheMap, CurrentOffset, &Vacb);
606  if (!NT_SUCCESS(Status))
607  {
609  return FALSE;
610  }
611 
612  _SEH2_TRY
613  {
614  if (!CcRosEnsureVacbResident(Vacb, Wait, FALSE, VacbOffset, VacbLength))
615  {
616  return FALSE;
617  }
618 
619  _SEH2_TRY
620  {
621  RtlCopyMemory((PVOID)((ULONG_PTR)Vacb->BaseAddress + VacbOffset), Buffer, VacbLength);
622  }
624  {
626  }
627  _SEH2_END;
628 
629  Buffer = (PVOID)((ULONG_PTR)Buffer + VacbLength);
630  CurrentOffset += VacbLength;
631 
632  /* Tell Mm */
633  Status = MmMakePagesDirty(NULL, Add2Ptr(Vacb->BaseAddress, VacbOffset), VacbLength);
634  if (!NT_SUCCESS(Status))
636  }
638  {
639  /* Do not mark the VACB as dirty if an exception was raised */
640  CcRosReleaseVacb(SharedCacheMap, Vacb, !_SEH2_AbnormalTermination(), FALSE);
641  }
642  _SEH2_END;
643  }
644 
645  /* Flush if needed */
646  if (FileObject->Flags & FO_WRITE_THROUGH)
647  CcFlushCache(FileObject->SectionObjectPointer, FileOffset, Length, NULL);
648 
649  return TRUE;
650 }
651 
652 /*
653  * @implemented
654  */
655 VOID
656 NTAPI
659  IN PCC_POST_DEFERRED_WRITE PostRoutine,
660  IN PVOID Context1,
661  IN PVOID Context2,
662  IN ULONG BytesToWrite,
663  IN BOOLEAN Retrying)
664 {
665  KIRQL OldIrql;
668 
669  CCTRACE(CC_API_DEBUG, "FileObject=%p PostRoutine=%p Context1=%p Context2=%p BytesToWrite=%lu Retrying=%d\n",
670  FileObject, PostRoutine, Context1, Context2, BytesToWrite, Retrying);
671 
672  /* Try to allocate a context for queueing the write operation */
674  /* If it failed, immediately execute the operation! */
675  if (Context == NULL)
676  {
677  PostRoutine(Context1, Context2);
678  return;
679  }
680 
681  Fcb = FileObject->FsContext;
682 
683  /* Otherwise, initialize the context */
685  Context->NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
686  Context->NodeByteSize = sizeof(DEFERRED_WRITE);
687  Context->FileObject = FileObject;
688  Context->PostRoutine = PostRoutine;
689  Context->Context1 = Context1;
690  Context->Context2 = Context2;
691  Context->BytesToWrite = BytesToWrite;
693 
694  /* And queue it */
695  if (Retrying)
696  {
697  /* To the top, if that's a retry */
699  &Context->DeferredWriteLinks,
701  }
702  else
703  {
704  /* To the bottom, if that's a first time */
706  &Context->DeferredWriteLinks,
708  }
709 
710  /* Try to execute the posted writes */
712 
713  /* Schedule a lazy writer run to handle deferred writes */
715  if (!LazyWriter.ScanActive)
716  {
718  }
720 }
721 
722 /*
723  * @unimplemented
724  */
725 VOID
726 NTAPI
730  IN ULONG Length,
731  IN ULONG PageCount,
732  OUT PVOID Buffer,
734 {
735  LARGE_INTEGER LargeFileOffset;
737 
738  CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu PageCount=%lu Buffer=%p\n",
739  FileObject, FileOffset, Length, PageCount, Buffer);
740 
741  DBG_UNREFERENCED_PARAMETER(PageCount);
742 
743  LargeFileOffset.QuadPart = FileOffset;
745  &LargeFileOffset,
746  Length,
747  TRUE,
748  Buffer,
749  IoStatus);
750  ASSERT(Success == TRUE);
751 }
752 
753 /*
754  * @unimplemented
755  */
756 VOID
757 NTAPI
761  IN ULONG Length,
762  IN PVOID Buffer)
763 {
764  LARGE_INTEGER LargeFileOffset;
766 
767  CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%lu Length=%lu Buffer=%p\n",
769 
770  LargeFileOffset.QuadPart = FileOffset;
772  &LargeFileOffset,
773  Length,
774  TRUE,
775  Buffer);
776  ASSERT(Success == TRUE);
777 }
778 
779 /*
780  * @implemented
781  */
782 BOOLEAN
783 NTAPI
786  IN PLARGE_INTEGER StartOffset,
787  IN PLARGE_INTEGER EndOffset,
788  IN BOOLEAN Wait)
789 {
793  PROS_VACB Vacb;
794  PROS_SHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
795 
796  CCTRACE(CC_API_DEBUG, "FileObject=%p StartOffset=%I64u EndOffset=%I64u Wait=%d\n",
797  FileObject, StartOffset->QuadPart, EndOffset->QuadPart, Wait);
798 
799  DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
800  "Wait %u)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
801  Wait);
802 
803  Length = EndOffset->QuadPart - StartOffset->QuadPart;
804  WriteOffset.QuadPart = StartOffset->QuadPart;
805 
806  if (!SharedCacheMap)
807  {
808  /* Make this a non-cached write */
810  KEVENT Event;
811  PMDL Mdl;
812  ULONG i;
813  ULONG CurrentLength;
814  PPFN_NUMBER PfnArray;
815 
816  /* Setup our Mdl */
818  if (!Mdl)
820 
821  PfnArray = MmGetMdlPfnArray(Mdl);
822  for (i = 0; i < BYTES_TO_PAGES(Mdl->ByteCount); i++)
823  PfnArray[i] = CcZeroPage;
824  Mdl->MdlFlags |= MDL_PAGES_LOCKED;
825 
826  /* Perform the write sequencially */
827  while (Length > 0)
828  {
829  CurrentLength = min(Length, MAX_ZERO_LENGTH);
830 
831  Mdl->ByteCount = CurrentLength;
832 
835  if (Status == STATUS_PENDING)
836  {
838  Status = Iosb.Status;
839  }
840  if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
841  {
842  MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
843  }
844  if (!NT_SUCCESS(Status))
845  {
846  IoFreeMdl(Mdl);
848  }
849  WriteOffset.QuadPart += CurrentLength;
850  Length -= CurrentLength;
851  }
852 
853  IoFreeMdl(Mdl);
854 
855  return TRUE;
856  }
857 
858  /* See if we should simply truncate the valid data length */
859  if ((StartOffset->QuadPart < SharedCacheMap->ValidDataLength.QuadPart) && (EndOffset->QuadPart >= SharedCacheMap->ValidDataLength.QuadPart))
860  {
861  DPRINT1("Truncating VDL.\n");
862  SharedCacheMap->ValidDataLength = *StartOffset;
863  return TRUE;
864  }
865 
866  ASSERT(EndOffset->QuadPart <= SharedCacheMap->SectionSize.QuadPart);
867 
868  while(WriteOffset.QuadPart < EndOffset->QuadPart)
869  {
870  ULONG VacbOffset = WriteOffset.QuadPart % VACB_MAPPING_GRANULARITY;
871  ULONG VacbLength = min(Length, VACB_MAPPING_GRANULARITY - VacbOffset);
872 
873  Status = CcRosGetVacb(SharedCacheMap, WriteOffset.QuadPart, &Vacb);
874  if (!NT_SUCCESS(Status))
875  {
877  return FALSE;
878  }
879 
880  _SEH2_TRY
881  {
882  if (!CcRosEnsureVacbResident(Vacb, Wait, FALSE, VacbOffset, VacbLength))
883  {
884  return FALSE;
885  }
886 
887  RtlZeroMemory((PVOID)((ULONG_PTR)Vacb->BaseAddress + VacbOffset), VacbLength);
888 
889  WriteOffset.QuadPart += VacbLength;
890  Length -= VacbLength;
891 
892  /* Tell Mm */
893  Status = MmMakePagesDirty(NULL, Add2Ptr(Vacb->BaseAddress, VacbOffset), VacbLength);
894  if (!NT_SUCCESS(Status))
896  }
898  {
899  /* Do not mark the VACB as dirty if an exception was raised */
900  CcRosReleaseVacb(SharedCacheMap, Vacb, !_SEH2_AbnormalTermination(), FALSE);
901  }
902  _SEH2_END;
903  }
904 
905  /* Flush if needed */
906  if (FileObject->Flags & FO_WRITE_THROUGH)
907  CcFlushCache(FileObject->SectionObjectPointer, StartOffset, EndOffset->QuadPart - StartOffset->QuadPart, NULL);
908 
909  return TRUE;
910 }
#define IN
Definition: typedefs.h:39
#define InterlockedAnd
Definition: interlocked.h:62
BOOLEAN LimitModifiedPages
Definition: cctypes.h:178
Definition: cc.h:206
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG CcDirtyPageThreshold
Definition: view.c:55
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define Add2Ptr(PTR, INC)
PVOID BaseAddress
Definition: cc.h:209
#define MmGetMdlPfnArray(_Mdl)
#define DbgPrint
Definition: hal.h:12
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
LARGE_INTEGER SectionSize
Definition: cc.h:177
LARGE_INTEGER BeyondLastByte2
Definition: cctypes.h:80
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:318
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
ULONG CcDataFlushes
Definition: copy.c:44
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:167
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN BOOLEAN Retrying)
Definition: copy.c:281
unsigned char * PUCHAR
Definition: retypes.h:3
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET WriteOffset
Definition: wdfusb.h:1914
FORCEINLINE PLIST_ENTRY RemoveTailList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:154
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:198
LONG NTSTATUS
Definition: precomp.h:26
#define FO_RANDOM_ACCESS
Definition: iotypes.h:1796
NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN MyWait, PPFN_NUMBER AllocatedPage)
Definition: balance.c:280
#define ExRaiseStatus
Definition: ntoskrnl.h:104
ULONG CcRosTraceLevel
Definition: copy.c:31
#define MC_SYSTEM
Definition: mm.h:104
VOID NTAPI MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:122
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
ULONG CcFastMdlReadWait
Definition: copy.c:32
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
NTSTATUS CcRosGetVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:863
VOID CcPostDeferredWrites(VOID)
Definition: copy.c:73
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:465
_SEH2_TRY
Definition: create.c:4226
VOID NTAPI CcScheduleReadAhead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length)
Definition: cachesub.c:92
uint32_t ULONG_PTR
Definition: typedefs.h:65
VOID CcPerformReadAhead(IN PFILE_OBJECT FileObject)
Definition: copy.c:130
DWORD ExceptionCode
Definition: compat.h:208
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG * PPFN_NUMBER
Definition: ke.h:9
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:727
PLIST_ENTRY NTAPI ExInterlockedRemoveHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:166
ULONG PFN_NUMBER
Definition: ke.h:9
LAZY_WRITER LazyWriter
Definition: lazywrite.c:37
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
BOOLEAN NTAPI IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)
Definition: file.c:3277
#define FALSE
Definition: types.h:117
VOID(NTAPI * PCC_POST_DEFERRED_WRITE)(_In_ PVOID Context1, _In_ PVOID Context2)
Definition: cctypes.h:66
ULONG CcFastReadResourceMiss
Definition: copy.c:37
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
NTSTATUS CcRosRequestVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, LONGLONG FileOffset, PROS_VACB *Vacb)
Definition: view.c:914
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:828
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:467
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
LARGE_INTEGER BeyondLastByte1
Definition: cctypes.h:78
unsigned char BOOLEAN
VOID NTAPI CcFastCopyWrite(IN PFILE_OBJECT FileObject, IN ULONG FileOffset, IN ULONG Length, IN PVOID Buffer)
Definition: copy.c:758
#define NODE_TYPE_DEFERRED_WRITE
Definition: cc.h:286
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
ULONG ReadLength
Definition: bufpool.h:45
#define MI_SET_USAGE(x)
Definition: mm.h:306
PCACHE_MANAGER_CALLBACKS Callbacks
Definition: cc.h:185
void * PVOID
Definition: retypes.h:9
ULONG CcFastReadNotPossible
Definition: copy.c:34
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
KIRQL OldIrql
Definition: mm.h:1502
KSPIN_LOCK ReadAheadSpinLock
Definition: cctypes.h:83
Status
Definition: gdiplustypes.h:24
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:657
int64_t LONGLONG
Definition: typedefs.h:68
ULONG CcDataPages
Definition: copy.c:43
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
#define CC_API_DEBUG
Definition: cc.h:11
#define ASSERT(a)
Definition: mode.c:44
LIST_ENTRY DeferredWriteLinks
Definition: cctypes.h:173
return Iosb
Definition: create.c:4402
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:221
struct _DEFERRED_WRITE DEFERRED_WRITE
enum _CC_CAN_WRITE_RETRY CC_CAN_WRITE_RETRY
#define ObDereferenceObject
Definition: obfuncs.h:203
LIST_ENTRY CcDeferredWrites
Definition: view.c:57
BOOLEAN ScanActive
Definition: cc.h:246
ULONG CcFastReadNoWait
Definition: copy.c:36
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
#define CCTRACE(x, fmt,...)
Definition: cc.h:36
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
static PFN_NUMBER CcZeroPage
Definition: copy.c:19
* PFILE_OBJECT
Definition: iotypes.h:1998
static int CcpCheckInvalidUserBuffer(PEXCEPTION_POINTERS Except, PVOID Buffer, ULONG Length)
Definition: copy.c:442
#define FSRTL_FLAG_LIMIT_MODIFIED_PAGES
Definition: fsrtltypes.h:47
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
PACQUIRE_FOR_READ_AHEAD AcquireForReadAhead
Definition: cctypes.h:41
KSPIN_LOCK CcDeferredWriteSpinLock
Definition: view.c:58
ULONG Flags
Definition: ntfs.h:536
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG MmThrottleBottom
Definition: mminit.c:397
#define BYTES_TO_PAGES(Size)
ULONG CcTotalDirtyPages
Definition: view.c:56
_CC_CAN_WRITE_RETRY
Definition: copy.c:23
PRELEASE_FROM_READ_AHEAD ReleaseFromReadAhead
Definition: cctypes.h:42
LARGE_INTEGER FileOffset1
Definition: cctypes.h:77
ULONG CcFastReadWait
Definition: copy.c:35
Definition: typedefs.h:119
Definition: copy.c:25
VOID NTAPI CcInitCacheZeroPage(VOID)
Definition: copy.c:56
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT _In_ PTDI_PNP_CONTEXT Context2
Definition: tdikrnl.h:1094
ULONG MmThrottleTop
Definition: mminit.c:396
VOID CcScheduleLazyWriteScan(IN BOOLEAN NoDelay)
Definition: lazywrite.c:200
PFILE_OBJECT FileObject
Definition: cctypes.h:171
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
PVOID Context1
Definition: cctypes.h:176
ULONG CcFastMdlReadNotPossible
Definition: copy.c:33
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI MmMakePagesDirty(_In_ PEPROCESS Process, _In_ PVOID Address, _In_ ULONG Length)
Definition: section.c:5052
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
BOOLEAN CcRosEnsureVacbResident(_In_ PROS_VACB Vacb, _In_ BOOLEAN Wait, _In_ BOOLEAN NoRead, _In_ ULONG Offset, _In_ ULONG Length)
Definition: view.c:816
LARGE_INTEGER ReadAheadOffset[2]
Definition: cctypes.h:81
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
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
PFN_NUMBER Total
Definition: mm.h:432
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ PNET_PNP_EVENT _In_ PTDI_PNP_CONTEXT Context1
Definition: tdikrnl.h:1094
_SEH2_FINALLY
Definition: create.c:4371
#define min(a, b)
Definition: monoChain.cc:55
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:1144
#define NULL
Definition: types.h:112
PCC_POST_DEFERRED_WRITE PostRoutine
Definition: cctypes.h:175
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
#define DPRINT1
Definition: precomp.h:8
LARGE_INTEGER CcIdleDelay
Definition: lazywrite.c:46
LARGE_INTEGER FileOffset2
Definition: cctypes.h:79
#define VACB_MAPPING_GRANULARITY
BOOLEAN NTAPI CcZeroData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER StartOffset, IN PLARGE_INTEGER EndOffset, IN BOOLEAN Wait)
Definition: copy.c:784
struct tagContext Context
Definition: acpixf.h:1034
PVOID LazyWriteContext
Definition: cc.h:186
#define OUT
Definition: typedefs.h:40
LARGE_INTEGER FileSize
Definition: cc.h:175
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
Definition: copy.c:570
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:155
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
LARGE_INTEGER ValidDataLength
Definition: cc.h:178
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
NTSTATUS CcRosReleaseVacb(PROS_SHARED_CACHE_MAP SharedCacheMap, PROS_VACB Vacb, BOOLEAN Dirty, BOOLEAN Mapped)
Definition: view.c:453
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
ULONG BytesToWrite
Definition: cctypes.h:172
#define STATUS_SUCCESS
Definition: shellext.h:65
void Clear(USHORT Window)
Definition: hardware.c:684
DWORD NumberParameters
Definition: compat.h:212
#define DPRINT
Definition: sndvol32.h:71
_In_ PFCB Fcb
Definition: cdprocs.h:159
ULONG UlongFlags
Definition: cctypes.h:73
#define PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE
Definition: cctypes.h:64
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
PKEVENT Event
Definition: cctypes.h:174
ULONG DirtyPageThreshold
Definition: cc.h:188
PVOID Context2
Definition: cctypes.h:177
PLIST_ENTRY NTAPI ExInterlockedInsertHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:114
ULONG DirtyPages
Definition: cc.h:180
ULONG ReadAheadLength[2]
Definition: cctypes.h:82
LONGLONG QuadPart
Definition: typedefs.h:114
#define FO_WRITE_THROUGH
Definition: iotypes.h:1779
#define MAX_ZERO_LENGTH
Definition: copy.c:21