3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/cc/view.c
23 * PURPOSE: Cache manager
24 * PROGRAMMER: David Welch (welch@mcmail.com)
25 * PORTABILITY: Checked
30 /* NOTES **********************************************************************
32 * This is not the NT implementation of a file cache nor anything much like
35 * The general procedure for a filesystem to implement a read or write
36 * dispatch routine is as follows
38 * (1) If caching for the FCB hasn't been initiated then so do by calling
39 * CcInitializeFileCache.
41 * (2) For each 4k region which is being read or written obtain a cache page
42 * by calling CcRequestCachePage.
44 * (3) If either the page is being read or not completely written, and it is
45 * not up to date then read its data from the underlying medium. If the read
46 * fails then call CcReleaseCachePage with VALID as FALSE and return a error.
48 * (4) Copy the data into or out of the page as necessary.
50 * (5) Release the cache page
52 /* INCLUDES ******************************************************************/
54 #include <ddk/ntddk.h>
55 #include <ddk/ntifs.h>
56 #include <internal/mm.h>
57 #include <internal/cc.h>
58 #include <internal/pool.h>
59 #include <ntos/minmax.h>
62 #include <internal/debug.h>
64 /* GLOBALS *******************************************************************/
66 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
67 #define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N)
69 #define TAG_CSEG TAG('C', 'S', 'E', 'G')
70 #define TAG_BCB TAG('B', 'C', 'B', ' ')
72 static LIST_ENTRY DirtySegmentListHead;
73 static LIST_ENTRY CacheSegmentListHead;
74 static LIST_ENTRY CacheSegmentLRUListHead;
76 static FAST_MUTEX ViewLock;
78 void * alloca(size_t size);
81 CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
83 /* FUNCTIONS *****************************************************************/
86 CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment)
90 Status = WriteCacheSegment(CacheSegment);
91 if (NT_SUCCESS(Status))
93 ExAcquireFastMutex(&ViewLock);
94 KeAcquireSpinLock(&CacheSegment->Bcb->BcbLock, &oldIrql);
95 CacheSegment->Dirty = FALSE;
96 RemoveEntryList(&CacheSegment->DirtySegmentListEntry);
97 CacheSegment->ReferenceCount--;
98 KeReleaseSpinLock(&CacheSegment->Bcb->BcbLock, oldIrql);
99 ExReleaseFastMutex(&ViewLock);
105 CcRosFlushDirtyPages(ULONG Target, PULONG Count)
107 PLIST_ENTRY current_entry;
108 PCACHE_SEGMENT current;
109 ULONG PagesPerSegment;
113 DPRINT("CcRosFlushDirtyPages(Target %d)\n", Target);
117 ExAcquireFastMutex(&ViewLock);
118 current_entry = DirtySegmentListHead.Flink;
119 while (current_entry != &DirtySegmentListHead && Target > 0)
121 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
122 DirtySegmentListEntry);
123 current_entry = current_entry->Flink;
124 Locked = ExTryToAcquireFastMutex(¤t->Lock);
129 assert(current->Dirty);
130 if (current->ReferenceCount > 1)
132 ExReleaseFastMutex(¤t->Lock);
135 ExReleaseFastMutex(&ViewLock);
136 PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
137 Status = CcRosFlushCacheSegment(current);
138 ExReleaseFastMutex(¤t->Lock);
139 if (!NT_SUCCESS(Status))
141 DPRINT1("CC: Failed to flush cache segment.\n");
145 (*Count) += PagesPerSegment;
146 Target -= PagesPerSegment;
148 ExAcquireFastMutex(&ViewLock);
149 current_entry = DirtySegmentListHead.Flink;
151 ExReleaseFastMutex(&ViewLock);
152 DPRINT("CcRosTrimCache() finished\n");
153 return(STATUS_SUCCESS);
157 CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
159 * FUNCTION: Try to free some memory from the file cache.
161 * Target - The number of pages to be freed.
162 * Priority - The priority of free (currently unused).
163 * NrFreed - Points to a variable where the number of pages
164 * actually freed is returned.
167 PLIST_ENTRY current_entry;
168 PCACHE_SEGMENT current;
169 ULONG PagesPerSegment;
174 DPRINT("CcRosTrimCache(Target %d)\n", Target);
178 InitializeListHead(&FreeList);
180 ExAcquireFastMutex(&ViewLock);
181 current_entry = CacheSegmentLRUListHead.Flink;
182 while (current_entry != &CacheSegmentLRUListHead && Target > 0)
184 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
185 CacheSegmentLRUListEntry);
186 current_entry = current_entry->Flink;
188 KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql);
189 if (current->ReferenceCount == 0)
191 RemoveEntryList(¤t->BcbSegmentListEntry);
192 KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
193 RemoveEntryList(¤t->CacheSegmentListEntry);
194 RemoveEntryList(¤t->CacheSegmentLRUListEntry);
195 InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
199 KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
202 ExReleaseFastMutex(&ViewLock);
204 while (!IsListEmpty(&FreeList))
206 current_entry = RemoveHeadList(&FreeList);
207 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
208 BcbSegmentListEntry);
209 PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
210 PagesFreed = min(PagesPerSegment, Target);
211 Target -= PagesFreed;
212 (*NrFreed) += PagesFreed;
213 CcRosInternalFreeCacheSegment(current);
216 DPRINT("CcRosTrimCache() finished\n");
217 return(STATUS_SUCCESS);
221 CcRosReleaseCacheSegment(PBCB Bcb,
222 PCACHE_SEGMENT CacheSeg,
227 BOOLEAN WasDirty = CacheSeg->Dirty;
230 DPRINT("CcReleaseCacheSegment(Bcb %x, CacheSeg %x, Valid %d)\n",
231 Bcb, CacheSeg, Valid);
233 CacheSeg->Valid = Valid;
234 CacheSeg->Dirty = CacheSeg->Dirty || Dirty;
236 ExAcquireFastMutex(&ViewLock);
237 if (!WasDirty && CacheSeg->Dirty)
239 InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
241 RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
242 InsertTailList(&CacheSegmentLRUListHead, &CacheSeg->CacheSegmentLRUListEntry);
246 CacheSeg->MappedCount++;
248 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
249 CacheSeg->ReferenceCount--;
250 if (Mapped && CacheSeg->MappedCount == 1)
252 CacheSeg->ReferenceCount++;
254 if (!WasDirty && CacheSeg->Dirty)
256 CacheSeg->ReferenceCount++;
258 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
259 ExReleaseFastMutex(&ViewLock);
260 ExReleaseFastMutex(&CacheSeg->Lock);
262 return(STATUS_SUCCESS);
265 PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
267 PLIST_ENTRY current_entry;
268 PCACHE_SEGMENT current;
271 DPRINT("CcRosLookupCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
273 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
274 current_entry = Bcb->BcbSegmentListHead.Flink;
275 while (current_entry != &Bcb->BcbSegmentListHead)
277 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
278 BcbSegmentListEntry);
279 if (current->FileOffset <= FileOffset &&
280 (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
282 current->ReferenceCount++;
283 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
286 current_entry = current_entry->Flink;
288 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
293 CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset)
295 PCACHE_SEGMENT CacheSeg;
298 DPRINT("CcRosMarkDirtyCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
300 CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
301 if (CacheSeg == NULL)
305 ExAcquireFastMutex(&CacheSeg->Lock);
306 if (!CacheSeg->Dirty)
308 ExAcquireFastMutex(&ViewLock);
309 InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
310 ExReleaseFastMutex(&ViewLock);
314 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
315 CacheSeg->ReferenceCount--;
316 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
320 CacheSeg->Dirty = TRUE;
321 ExReleaseFastMutex(&CacheSeg->Lock);
323 return(STATUS_SUCCESS);
327 CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
329 PCACHE_SEGMENT CacheSeg;
333 DPRINT("CcRosUnmapCacheSegment(Bcb %x, FileOffset %d, NowDirty %d)\n",
334 Bcb, FileOffset, NowDirty);
336 CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
337 if (CacheSeg == NULL)
339 return(STATUS_UNSUCCESSFUL);
341 ExAcquireFastMutex(&CacheSeg->Lock);
343 WasDirty = CacheSeg->Dirty;
344 CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
346 CacheSeg->MappedCount--;
348 if (!WasDirty && NowDirty)
350 ExAcquireFastMutex(&ViewLock);
351 InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
352 ExReleaseFastMutex(&ViewLock);
355 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
356 CacheSeg->ReferenceCount--;
357 if (!WasDirty && NowDirty)
359 CacheSeg->ReferenceCount++;
361 if (CacheSeg->MappedCount == 0)
363 CacheSeg->ReferenceCount--;
365 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
367 ExReleaseFastMutex(&CacheSeg->Lock);
368 return(STATUS_SUCCESS);
372 CcRosCreateCacheSegment(PBCB Bcb,
374 PCACHE_SEGMENT* CacheSeg,
378 PCACHE_SEGMENT current;
379 PLIST_ENTRY current_entry;
383 DPRINT("CcRosCreateCacheSegment()\n");
385 current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
387 current->Valid = FALSE;
388 current->Dirty = FALSE;
389 current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
391 current->MappedCount = 0;
392 current->DirtySegmentListEntry.Flink = NULL;
393 current->DirtySegmentListEntry.Blink = NULL;
394 current->ReferenceCount = 1;
395 ExInitializeFastMutex(¤t->Lock);
396 ExAcquireFastMutex(¤t->Lock);
397 ExAcquireFastMutex(&ViewLock);
400 /* There is window between the call to CcRosLookupCacheSegment
401 * and CcRosCreateCacheSegment. We must check if a segment on
402 * the fileoffset exist. If there exist a segment, we release
403 * our new created segment and return the existing one.
405 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
406 current_entry = Bcb->BcbSegmentListHead.Flink;
407 while (current_entry != &Bcb->BcbSegmentListHead)
409 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
410 BcbSegmentListEntry);
411 if (current->FileOffset <= FileOffset &&
412 (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
414 current->ReferenceCount++;
415 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
416 ExReleaseFastMutex(&(*CacheSeg)->Lock);
417 ExReleaseFastMutex(&ViewLock);
418 ExFreePool(*CacheSeg);
422 ExAcquireFastMutex(¤t->Lock);
424 return STATUS_SUCCESS;
426 current_entry = current_entry->Flink;
428 /* There was no existing segment. */
430 InsertTailList(&Bcb->BcbSegmentListHead, ¤t->BcbSegmentListEntry);
431 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
432 InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
433 InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
434 ExReleaseFastMutex(&ViewLock);
436 MmLockAddressSpace(MmGetKernelAddressSpace());
437 current->BaseAddress = NULL;
438 Status = MmCreateMemoryArea(NULL,
439 MmGetKernelAddressSpace(),
440 MEMORY_AREA_CACHE_SEGMENT,
441 ¤t->BaseAddress,
442 Bcb->CacheSegmentSize,
444 (PMEMORY_AREA*)¤t->MemoryArea,
446 MmUnlockAddressSpace(MmGetKernelAddressSpace());
447 if (!NT_SUCCESS(Status))
451 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
453 PHYSICAL_ADDRESS Page;
455 Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
456 if (!NT_SUCCESS(Status))
461 Status = MmCreateVirtualMapping(NULL,
462 current->BaseAddress + (i * PAGE_SIZE),
466 if (!NT_SUCCESS(Status))
473 ExReleaseFastMutex(¤t->Lock);
476 return(STATUS_SUCCESS);
480 CcRosGetCacheSegmentChain(PBCB Bcb,
483 PCACHE_SEGMENT* CacheSeg)
485 PCACHE_SEGMENT current;
487 PCACHE_SEGMENT* CacheSegList;
488 PCACHE_SEGMENT Previous = NULL;
490 DPRINT("CcRosGetCacheSegmentChain()\n");
492 Length = ROUND_UP(Length, Bcb->CacheSegmentSize);
494 CacheSegList = alloca(sizeof(PCACHE_SEGMENT) *
495 (Length / Bcb->CacheSegmentSize));
498 * Look for a cache segment already mapping the same data.
500 for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
502 ULONG CurrentOffset = FileOffset + (i * Bcb->CacheSegmentSize);
503 current = CcRosLookupCacheSegment(Bcb, CurrentOffset);
506 CacheSegList[i] = current;
510 CcRosCreateCacheSegment(Bcb, CurrentOffset, ¤t, FALSE);
511 CacheSegList[i] = current;
515 for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
517 ExAcquireFastMutex(&CacheSegList[i]->Lock);
520 *CacheSeg = CacheSegList[i];
521 Previous = CacheSegList[i];
525 Previous->NextInChain = CacheSegList[i];
526 Previous = CacheSegList[i];
529 Previous->NextInChain = NULL;
531 return(STATUS_SUCCESS);
535 CcRosGetCacheSegment(PBCB Bcb,
540 PCACHE_SEGMENT* CacheSeg)
542 PCACHE_SEGMENT current;
545 DPRINT("CcRosGetCacheSegment()\n");
548 * Look for a cache segment already mapping the same data.
550 current = CcRosLookupCacheSegment(Bcb, FileOffset);
553 ExAcquireFastMutex(¤t->Lock);
558 * Otherwise create a new segment.
560 Status = CcRosCreateCacheSegment(Bcb, FileOffset, ¤t, TRUE);
563 * Return information about the segment to the caller.
565 *UptoDate = current->Valid;
566 *BaseAddress = current->BaseAddress;
567 DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress);
569 *BaseOffset = current->FileOffset;
570 return(STATUS_SUCCESS);
574 CcRosRequestCacheSegment(PBCB Bcb,
578 PCACHE_SEGMENT* CacheSeg)
580 * FUNCTION: Request a page mapping for a BCB
585 if ((FileOffset % Bcb->CacheSegmentSize) != 0)
587 CPRINT("Bad fileoffset %x should be multiple of %x",
588 FileOffset, Bcb->CacheSegmentSize);
592 return(CcRosGetCacheSegment(Bcb,
601 CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
602 PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
604 assert(SwapEntry == 0);
605 if (PhysAddr.QuadPart != 0)
607 MmReleasePageMemoryConsumer(MC_CACHE, PhysAddr);
612 CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
614 * FUNCTION: Releases a cache segment associated with a BCB
618 DPRINT("Freeing cache segment %x\n", CacheSeg);
620 MmLockAddressSpace(MmGetKernelAddressSpace());
621 MmFreeMemoryArea(MmGetKernelAddressSpace(),
622 CacheSeg->BaseAddress,
623 CacheSeg->Bcb->CacheSegmentSize,
626 MmUnlockAddressSpace(MmGetKernelAddressSpace());
627 ExFreePool(CacheSeg);
628 return(STATUS_SUCCESS);
632 CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
637 DPRINT("CcRosFreeCacheSegment(Bcb %x, CacheSeg %x)\n",
640 ExAcquireFastMutex(&ViewLock);
641 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
642 RemoveEntryList(&CacheSeg->BcbSegmentListEntry);
643 RemoveEntryList(&CacheSeg->CacheSegmentListEntry);
644 RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
647 RemoveEntryList(&CacheSeg->DirtySegmentListEntry);
649 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
650 ExReleaseFastMutex(&ViewLock);
652 Status = CcRosInternalFreeCacheSegment(CacheSeg);
657 CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
658 IN PLARGE_INTEGER FileOffset OPTIONAL,
660 OUT PIO_STATUS_BLOCK IoStatus)
663 LARGE_INTEGER Offset;
664 PCACHE_SEGMENT current;
668 DPRINT("CcFlushCache(SectionObjectPointers %x, FileOffset %x, Length %d, IoStatus %x)\n",
669 SectionObjectPointers, FileOffset, Length, IoStatus);
671 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
673 Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
676 Offset = *FileOffset;
680 Offset.QuadPart = 0LL;
681 Length = Bcb->FileSize.u.LowPart;
686 IoStatus->Status = STATUS_SUCCESS;
687 IoStatus->Information = 0;
692 current = CcRosLookupCacheSegment (Bcb, Offset.u.LowPart);
695 ExAcquireFastMutex(¤t->Lock);
698 Status = CcRosFlushCacheSegment(current);
699 if (!NT_SUCCESS(Status) && IoStatus != NULL)
701 IoStatus->Status = Status;
704 ExReleaseFastMutex(¤t->Lock);
705 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
706 current->ReferenceCount--;
707 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
710 Offset.QuadPart += Bcb->CacheSegmentSize;
711 if (Length > Bcb->CacheSegmentSize)
713 Length -= Bcb->CacheSegmentSize;
725 IoStatus->Status = STATUS_INVALID_PARAMETER;
731 CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
733 * FUNCTION: Releases the BCB associated with a file object
736 PLIST_ENTRY current_entry;
737 PCACHE_SEGMENT current;
742 DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n",
743 Bcb->FileObject, Bcb);
745 ExReleaseFastMutex(&ViewLock);
747 CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
749 ExAcquireFastMutex(&ViewLock);
751 if (Bcb->RefCount == 0)
753 MmFreeSectionSegments(Bcb->FileObject);
756 * Release all cache segments.
758 InitializeListHead(&FreeList);
760 FileObject->SectionObjectPointers->SharedCacheMap = NULL;
761 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
762 current_entry = Bcb->BcbSegmentListHead.Flink;
763 while (!IsListEmpty(&Bcb->BcbSegmentListHead))
765 current_entry = RemoveTailList(&Bcb->BcbSegmentListHead);
766 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
767 RemoveEntryList(¤t->CacheSegmentListEntry);
768 RemoveEntryList(¤t->CacheSegmentLRUListEntry);
771 RemoveEntryList(¤t->DirtySegmentListEntry);
773 InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
776 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
777 while (!IsListEmpty(&FreeList))
779 current_entry = RemoveTailList(&FreeList);
780 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
781 Status = CcRosInternalFreeCacheSegment(current);
784 ObDereferenceObject (Bcb->FileObject);
787 return(STATUS_SUCCESS);
790 VOID CcRosReferenceCache(PFILE_OBJECT FileObject)
793 ExAcquireFastMutex(&ViewLock);
794 Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
796 ExReleaseFastMutex(&ViewLock);
799 VOID CcRosDereferenceCache(PFILE_OBJECT FileObject)
802 ExAcquireFastMutex(&ViewLock);
803 Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
805 if (Bcb->RefCount == 0)
807 CcRosDeleteFileCache(FileObject, Bcb);
809 ExReleaseFastMutex(&ViewLock);
813 CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
815 * FUNCTION: Called by the file system when a handle to a file object
819 ExAcquireFastMutex(&ViewLock);
821 if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
823 if (FileObject->PrivateCacheMap != NULL)
825 FileObject->PrivateCacheMap = NULL;
828 if (Bcb->RefCount == 0)
830 CcRosDeleteFileCache(FileObject, Bcb);
833 ExReleaseFastMutex(&ViewLock);
834 return(STATUS_SUCCESS);
838 CcRosInitializeFileCache(PFILE_OBJECT FileObject,
840 ULONG CacheSegmentSize)
842 * FUNCTION: Initializes a BCB for a file object
845 DPRINT("CcRosInitializeFileCache(FileObject %x, *Bcb %x, CacheSegmentSize %d)\n",
846 FileObject, Bcb, CacheSegmentSize);
848 ExAcquireFastMutex(&ViewLock);
852 (*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB);
855 return(STATUS_UNSUCCESSFUL);
858 ObReferenceObjectByPointer(FileObject,
862 (*Bcb)->FileObject = FileObject;
863 (*Bcb)->CacheSegmentSize = CacheSegmentSize;
864 if (FileObject->FsContext)
866 (*Bcb)->AllocationSize =
867 ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize;
869 ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize;
871 KeInitializeSpinLock(&(*Bcb)->BcbLock);
872 InitializeListHead(&(*Bcb)->BcbSegmentListHead);
873 FileObject->SectionObjectPointers->SharedCacheMap = *Bcb;
875 if (FileObject->PrivateCacheMap == NULL)
877 FileObject->PrivateCacheMap = *Bcb;
880 ExReleaseFastMutex(&ViewLock);
882 return(STATUS_SUCCESS);
886 CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
889 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
891 Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
892 return Bcb->FileObject;
900 DPRINT("CcInitView()\n");
901 InitializeListHead(&CacheSegmentListHead);
902 InitializeListHead(&DirtySegmentListHead);
903 InitializeListHead(&CacheSegmentLRUListHead);
904 ExInitializeFastMutex(&ViewLock);
905 MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache);
906 CcInitCacheZeroPage();