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;
79 void * alloca(size_t size);
82 CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
83 #endif /* LIBCAPTIVE */
85 /* FUNCTIONS *****************************************************************/
90 CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment)
94 Status = WriteCacheSegment(CacheSegment);
95 if (NT_SUCCESS(Status))
97 ExAcquireFastMutex(&ViewLock);
98 KeAcquireSpinLock(&CacheSegment->Bcb->BcbLock, &oldIrql);
99 CacheSegment->Dirty = FALSE;
100 RemoveEntryList(&CacheSegment->DirtySegmentListEntry);
101 CacheSegment->ReferenceCount--;
102 KeReleaseSpinLock(&CacheSegment->Bcb->BcbLock, oldIrql);
103 ExReleaseFastMutex(&ViewLock);
109 CcRosFlushDirtyPages(ULONG Target, PULONG Count)
111 PLIST_ENTRY current_entry;
112 PCACHE_SEGMENT current;
113 ULONG PagesPerSegment;
117 DPRINT("CcRosFlushDirtyPages(Target %d)\n", Target);
121 ExAcquireFastMutex(&ViewLock);
122 current_entry = DirtySegmentListHead.Flink;
123 while (current_entry != &DirtySegmentListHead && Target > 0)
125 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
126 DirtySegmentListEntry);
127 current_entry = current_entry->Flink;
128 Locked = ExTryToAcquireFastMutex(¤t->Lock);
133 assert(current->Dirty);
134 if (current->ReferenceCount > 1)
136 ExReleaseFastMutex(¤t->Lock);
139 ExReleaseFastMutex(&ViewLock);
140 PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
141 Status = CcRosFlushCacheSegment(current);
142 ExReleaseFastMutex(¤t->Lock);
143 if (!NT_SUCCESS(Status))
145 DPRINT1("CC: Failed to flush cache segment.\n");
149 (*Count) += PagesPerSegment;
150 Target -= PagesPerSegment;
152 ExAcquireFastMutex(&ViewLock);
153 current_entry = DirtySegmentListHead.Flink;
155 ExReleaseFastMutex(&ViewLock);
156 DPRINT("CcRosTrimCache() finished\n");
157 return(STATUS_SUCCESS);
161 CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
163 * FUNCTION: Try to free some memory from the file cache.
165 * Target - The number of pages to be freed.
166 * Priority - The priority of free (currently unused).
167 * NrFreed - Points to a variable where the number of pages
168 * actually freed is returned.
171 PLIST_ENTRY current_entry;
172 PCACHE_SEGMENT current;
173 ULONG PagesPerSegment;
178 DPRINT("CcRosTrimCache(Target %d)\n", Target);
182 InitializeListHead(&FreeList);
184 ExAcquireFastMutex(&ViewLock);
185 current_entry = CacheSegmentLRUListHead.Flink;
186 while (current_entry != &CacheSegmentLRUListHead && Target > 0)
188 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
189 CacheSegmentLRUListEntry);
190 current_entry = current_entry->Flink;
192 KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql);
193 if (current->ReferenceCount == 0)
195 RemoveEntryList(¤t->BcbSegmentListEntry);
196 KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
197 RemoveEntryList(¤t->CacheSegmentListEntry);
198 RemoveEntryList(¤t->CacheSegmentLRUListEntry);
199 InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
203 KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
206 ExReleaseFastMutex(&ViewLock);
208 while (!IsListEmpty(&FreeList))
210 current_entry = RemoveHeadList(&FreeList);
211 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
212 BcbSegmentListEntry);
213 PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
214 PagesFreed = min(PagesPerSegment, Target);
215 Target -= PagesFreed;
216 (*NrFreed) += PagesFreed;
217 CcRosInternalFreeCacheSegment(current);
220 DPRINT("CcRosTrimCache() finished\n");
221 return(STATUS_SUCCESS);
224 #endif /* LIBCAPTIVE */
227 CcRosReleaseCacheSegment(PBCB Bcb,
228 PCACHE_SEGMENT CacheSeg,
233 BOOLEAN WasDirty = CacheSeg->Dirty;
236 DPRINT("CcReleaseCacheSegment(Bcb %x, CacheSeg %x, Valid %d)\n",
237 Bcb, CacheSeg, Valid);
239 CacheSeg->Valid = Valid;
240 CacheSeg->Dirty = CacheSeg->Dirty || Dirty;
242 ExAcquireFastMutex(&ViewLock);
243 if (!WasDirty && CacheSeg->Dirty)
245 InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
247 RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
248 InsertTailList(&CacheSegmentLRUListHead, &CacheSeg->CacheSegmentLRUListEntry);
252 CacheSeg->MappedCount++;
254 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
255 CacheSeg->ReferenceCount--;
256 if (Mapped && CacheSeg->MappedCount == 1)
258 CacheSeg->ReferenceCount++;
260 if (!WasDirty && CacheSeg->Dirty)
262 CacheSeg->ReferenceCount++;
264 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
265 ExReleaseFastMutex(&ViewLock);
266 ExReleaseFastMutex(&CacheSeg->Lock);
268 return(STATUS_SUCCESS);
271 PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
273 PLIST_ENTRY current_entry;
274 PCACHE_SEGMENT current;
277 DPRINT("CcRosLookupCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
279 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
280 current_entry = Bcb->BcbSegmentListHead.Flink;
281 while (current_entry != &Bcb->BcbSegmentListHead)
283 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
284 BcbSegmentListEntry);
285 if (current->FileOffset <= FileOffset &&
286 (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
288 current->ReferenceCount++;
289 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
292 current_entry = current_entry->Flink;
294 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
301 CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset)
303 PCACHE_SEGMENT CacheSeg;
306 DPRINT("CcRosMarkDirtyCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
308 CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
309 if (CacheSeg == NULL)
313 ExAcquireFastMutex(&CacheSeg->Lock);
314 if (!CacheSeg->Dirty)
316 ExAcquireFastMutex(&ViewLock);
317 InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
318 ExReleaseFastMutex(&ViewLock);
322 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
323 CacheSeg->ReferenceCount--;
324 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
328 CacheSeg->Dirty = TRUE;
329 ExReleaseFastMutex(&CacheSeg->Lock);
331 return(STATUS_SUCCESS);
335 CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
337 PCACHE_SEGMENT CacheSeg;
341 DPRINT("CcRosUnmapCacheSegment(Bcb %x, FileOffset %d, NowDirty %d)\n",
342 Bcb, FileOffset, NowDirty);
344 CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
345 if (CacheSeg == NULL)
347 return(STATUS_UNSUCCESSFUL);
349 ExAcquireFastMutex(&CacheSeg->Lock);
351 WasDirty = CacheSeg->Dirty;
352 CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
354 CacheSeg->MappedCount--;
356 if (!WasDirty && NowDirty)
358 ExAcquireFastMutex(&ViewLock);
359 InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
360 ExReleaseFastMutex(&ViewLock);
363 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
364 CacheSeg->ReferenceCount--;
365 if (!WasDirty && NowDirty)
367 CacheSeg->ReferenceCount++;
369 if (CacheSeg->MappedCount == 0)
371 CacheSeg->ReferenceCount--;
373 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
375 ExReleaseFastMutex(&CacheSeg->Lock);
376 return(STATUS_SUCCESS);
379 #endif /* LIBCAPTIVE */
382 CcRosCreateCacheSegment(PBCB Bcb,
384 PCACHE_SEGMENT* CacheSeg,
389 #endif /* LIBCAPTIVE */
390 PCACHE_SEGMENT current;
391 PLIST_ENTRY current_entry;
395 DPRINT("CcRosCreateCacheSegment()\n");
397 current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
399 current->Valid = FALSE;
400 current->Dirty = FALSE;
401 current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
403 current->MappedCount = 0;
404 current->DirtySegmentListEntry.Flink = NULL;
405 current->DirtySegmentListEntry.Blink = NULL;
406 current->ReferenceCount = 1;
407 ExInitializeFastMutex(¤t->Lock);
408 ExAcquireFastMutex(¤t->Lock);
409 ExAcquireFastMutex(&ViewLock);
412 /* There is window between the call to CcRosLookupCacheSegment
413 * and CcRosCreateCacheSegment. We must check if a segment on
414 * the fileoffset exist. If there exist a segment, we release
415 * our new created segment and return the existing one.
417 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
418 current_entry = Bcb->BcbSegmentListHead.Flink;
419 while (current_entry != &Bcb->BcbSegmentListHead)
421 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
422 BcbSegmentListEntry);
423 if (current->FileOffset <= FileOffset &&
424 (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
426 current->ReferenceCount++;
427 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
428 ExReleaseFastMutex(&(*CacheSeg)->Lock);
429 ExReleaseFastMutex(&ViewLock);
430 ExFreePool(*CacheSeg);
434 ExAcquireFastMutex(¤t->Lock);
436 return STATUS_SUCCESS;
438 current_entry = current_entry->Flink;
440 /* There was no existing segment. */
442 InsertTailList(&Bcb->BcbSegmentListHead, ¤t->BcbSegmentListEntry);
443 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
444 InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
445 InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
446 ExReleaseFastMutex(&ViewLock);
448 MmLockAddressSpace(MmGetKernelAddressSpace());
449 current->BaseAddress = NULL;
450 Status = MmCreateMemoryArea(NULL,
451 MmGetKernelAddressSpace(),
452 MEMORY_AREA_CACHE_SEGMENT,
453 ¤t->BaseAddress,
454 Bcb->CacheSegmentSize,
456 (PMEMORY_AREA*)¤t->MemoryArea,
458 MmUnlockAddressSpace(MmGetKernelAddressSpace());
459 if (!NT_SUCCESS(Status))
464 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
466 PHYSICAL_ADDRESS Page;
468 Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
469 if (!NT_SUCCESS(Status))
474 Status = MmCreateVirtualMapping(NULL,
475 current->BaseAddress + (i * PAGE_SIZE),
479 if (!NT_SUCCESS(Status))
484 #else /* !LIBCAPTIVE */
485 /* libcaptive MmCreateMemoryArea() returns already allocated memory */
486 #endif /* !LIBCAPTIVE */
489 ExReleaseFastMutex(¤t->Lock);
492 return(STATUS_SUCCESS);
498 CcRosGetCacheSegmentChain(PBCB Bcb,
501 PCACHE_SEGMENT* CacheSeg)
503 PCACHE_SEGMENT current;
505 PCACHE_SEGMENT* CacheSegList;
506 PCACHE_SEGMENT Previous = NULL;
508 DPRINT("CcRosGetCacheSegmentChain()\n");
510 Length = ROUND_UP(Length, Bcb->CacheSegmentSize);
512 CacheSegList = alloca(sizeof(PCACHE_SEGMENT) *
513 (Length / Bcb->CacheSegmentSize));
516 * Look for a cache segment already mapping the same data.
518 for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
520 ULONG CurrentOffset = FileOffset + (i * Bcb->CacheSegmentSize);
521 current = CcRosLookupCacheSegment(Bcb, CurrentOffset);
524 CacheSegList[i] = current;
528 CcRosCreateCacheSegment(Bcb, CurrentOffset, ¤t, FALSE);
529 CacheSegList[i] = current;
533 for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
535 ExAcquireFastMutex(&CacheSegList[i]->Lock);
538 *CacheSeg = CacheSegList[i];
539 Previous = CacheSegList[i];
543 Previous->NextInChain = CacheSegList[i];
544 Previous = CacheSegList[i];
547 Previous->NextInChain = NULL;
549 return(STATUS_SUCCESS);
552 #endif /* LIBCAPTIVE */
555 CcRosGetCacheSegment(PBCB Bcb,
560 PCACHE_SEGMENT* CacheSeg)
562 PCACHE_SEGMENT current;
565 DPRINT("CcRosGetCacheSegment()\n");
568 * Look for a cache segment already mapping the same data.
570 current = CcRosLookupCacheSegment(Bcb, FileOffset);
573 ExAcquireFastMutex(¤t->Lock);
578 * Otherwise create a new segment.
580 Status = CcRosCreateCacheSegment(Bcb, FileOffset, ¤t, TRUE);
583 * Return information about the segment to the caller.
585 *UptoDate = current->Valid;
586 *BaseAddress = current->BaseAddress;
587 DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress);
589 *BaseOffset = current->FileOffset;
590 return(STATUS_SUCCESS);
594 CcRosRequestCacheSegment(PBCB Bcb,
598 PCACHE_SEGMENT* CacheSeg)
600 * FUNCTION: Request a page mapping for a BCB
605 if ((FileOffset % Bcb->CacheSegmentSize) != 0)
607 CPRINT("Bad fileoffset %x should be multiple of %x",
608 FileOffset, Bcb->CacheSegmentSize);
612 return(CcRosGetCacheSegment(Bcb,
623 CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
624 PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
626 assert(SwapEntry == 0);
627 if (PhysAddr.QuadPart != 0)
629 MmReleasePageMemoryConsumer(MC_CACHE, PhysAddr);
634 CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
636 * FUNCTION: Releases a cache segment associated with a BCB
640 DPRINT("Freeing cache segment %x\n", CacheSeg);
642 MmLockAddressSpace(MmGetKernelAddressSpace());
643 MmFreeMemoryArea(MmGetKernelAddressSpace(),
644 CacheSeg->BaseAddress,
645 CacheSeg->Bcb->CacheSegmentSize,
648 MmUnlockAddressSpace(MmGetKernelAddressSpace());
649 ExFreePool(CacheSeg);
650 return(STATUS_SUCCESS);
654 CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
659 DPRINT("CcRosFreeCacheSegment(Bcb %x, CacheSeg %x)\n",
662 ExAcquireFastMutex(&ViewLock);
663 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
664 RemoveEntryList(&CacheSeg->BcbSegmentListEntry);
665 RemoveEntryList(&CacheSeg->CacheSegmentListEntry);
666 RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
669 RemoveEntryList(&CacheSeg->DirtySegmentListEntry);
671 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
672 ExReleaseFastMutex(&ViewLock);
674 Status = CcRosInternalFreeCacheSegment(CacheSeg);
679 CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
680 IN PLARGE_INTEGER FileOffset OPTIONAL,
682 OUT PIO_STATUS_BLOCK IoStatus)
685 LARGE_INTEGER Offset;
686 PCACHE_SEGMENT current;
690 DPRINT("CcFlushCache(SectionObjectPointers %x, FileOffset %x, Length %d, IoStatus %x)\n",
691 SectionObjectPointers, FileOffset, Length, IoStatus);
693 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
695 Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
698 Offset = *FileOffset;
702 Offset.QuadPart = 0LL;
703 Length = Bcb->FileSize.u.LowPart;
708 IoStatus->Status = STATUS_SUCCESS;
709 IoStatus->Information = 0;
714 current = CcRosLookupCacheSegment (Bcb, Offset.u.LowPart);
717 ExAcquireFastMutex(¤t->Lock);
720 Status = CcRosFlushCacheSegment(current);
721 if (!NT_SUCCESS(Status) && IoStatus != NULL)
723 IoStatus->Status = Status;
726 ExReleaseFastMutex(¤t->Lock);
727 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
728 current->ReferenceCount--;
729 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
732 Offset.QuadPart += Bcb->CacheSegmentSize;
733 if (Length > Bcb->CacheSegmentSize)
735 Length -= Bcb->CacheSegmentSize;
747 IoStatus->Status = STATUS_INVALID_PARAMETER;
753 CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
755 * FUNCTION: Releases the BCB associated with a file object
758 PLIST_ENTRY current_entry;
759 PCACHE_SEGMENT current;
764 DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n",
765 Bcb->FileObject, Bcb);
767 ExReleaseFastMutex(&ViewLock);
769 CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
771 ExAcquireFastMutex(&ViewLock);
773 if (Bcb->RefCount == 0)
775 MmFreeSectionSegments(Bcb->FileObject);
778 * Release all cache segments.
780 InitializeListHead(&FreeList);
782 FileObject->SectionObjectPointers->SharedCacheMap = NULL;
783 KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
784 current_entry = Bcb->BcbSegmentListHead.Flink;
785 while (!IsListEmpty(&Bcb->BcbSegmentListHead))
787 current_entry = RemoveTailList(&Bcb->BcbSegmentListHead);
788 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
789 RemoveEntryList(¤t->CacheSegmentListEntry);
790 RemoveEntryList(¤t->CacheSegmentLRUListEntry);
793 RemoveEntryList(¤t->DirtySegmentListEntry);
795 InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
798 KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
799 while (!IsListEmpty(&FreeList))
801 current_entry = RemoveTailList(&FreeList);
802 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
803 Status = CcRosInternalFreeCacheSegment(current);
806 ObDereferenceObject (Bcb->FileObject);
809 return(STATUS_SUCCESS);
812 VOID CcRosReferenceCache(PFILE_OBJECT FileObject)
815 ExAcquireFastMutex(&ViewLock);
816 Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
818 ExReleaseFastMutex(&ViewLock);
821 VOID CcRosDereferenceCache(PFILE_OBJECT FileObject)
824 ExAcquireFastMutex(&ViewLock);
825 Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
827 if (Bcb->RefCount == 0)
829 CcRosDeleteFileCache(FileObject, Bcb);
831 ExReleaseFastMutex(&ViewLock);
835 CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
837 * FUNCTION: Called by the file system when a handle to a file object
841 ExAcquireFastMutex(&ViewLock);
843 if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
845 if (FileObject->PrivateCacheMap != NULL)
847 FileObject->PrivateCacheMap = NULL;
850 if (Bcb->RefCount == 0)
852 CcRosDeleteFileCache(FileObject, Bcb);
855 ExReleaseFastMutex(&ViewLock);
856 return(STATUS_SUCCESS);
860 CcRosInitializeFileCache(PFILE_OBJECT FileObject,
862 ULONG CacheSegmentSize)
864 * FUNCTION: Initializes a BCB for a file object
867 DPRINT("CcRosInitializeFileCache(FileObject %x, *Bcb %x, CacheSegmentSize %d)\n",
868 FileObject, Bcb, CacheSegmentSize);
870 ExAcquireFastMutex(&ViewLock);
874 (*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB);
877 return(STATUS_UNSUCCESSFUL);
880 ObReferenceObjectByPointer(FileObject,
884 (*Bcb)->FileObject = FileObject;
885 (*Bcb)->CacheSegmentSize = CacheSegmentSize;
886 if (FileObject->FsContext)
888 (*Bcb)->AllocationSize =
889 ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize;
891 ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize;
893 KeInitializeSpinLock(&(*Bcb)->BcbLock);
894 InitializeListHead(&(*Bcb)->BcbSegmentListHead);
895 FileObject->SectionObjectPointers->SharedCacheMap = *Bcb;
897 if (FileObject->PrivateCacheMap == NULL)
899 FileObject->PrivateCacheMap = *Bcb;
902 ExReleaseFastMutex(&ViewLock);
904 return(STATUS_SUCCESS);
908 CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
911 if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
913 Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
914 return Bcb->FileObject;
919 #endif /* LIBCAPTIVE */
924 DPRINT("CcInitView()\n");
925 InitializeListHead(&CacheSegmentListHead);
926 InitializeListHead(&DirtySegmentListHead);
927 InitializeListHead(&CacheSegmentLRUListHead);
928 ExInitializeFastMutex(&ViewLock);
930 MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache);
931 CcInitCacheZeroPage();
932 #endif /* LIBCAPTIVE */