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.
19 /* $Id: view.c,v 1.51 2002/09/30 20:55:33 chorns Exp $
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(PBCB Bcb
, PCACHE_SEGMENT CacheSeg
);
83 /* FUNCTIONS *****************************************************************/
86 CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment
)
89 Status
= WriteCacheSegment(CacheSegment
);
90 if (NT_SUCCESS(Status
))
92 CacheSegment
->Dirty
= FALSE
;
93 RemoveEntryList(&CacheSegment
->DirtySegmentListEntry
);
99 CcRosFlushDirtyPages(ULONG Target
, PULONG Count
)
101 PLIST_ENTRY current_entry
;
102 PCACHE_SEGMENT current
;
103 ULONG PagesPerSegment
;
107 DPRINT("CcRosFlushDirtyPages(Target %d)\n", Target
);
111 ExAcquireFastMutex(&ViewLock
);
112 current_entry
= DirtySegmentListHead
.Flink
;
113 while (current_entry
!= &DirtySegmentListHead
&& Target
> 0)
115 current
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
,
116 DirtySegmentListEntry
);
117 current_entry
= current_entry
->Flink
;
118 Locked
= ExTryToAcquireFastMutex(¤t
->Lock
);
123 assert(current
->Dirty
);
124 if (current
->ReferenceCount
> 0)
126 ExReleaseFastMutex(¤t
->Lock
);
129 current
->ReferenceCount
++;
130 ExReleaseFastMutex(&ViewLock
);
131 PagesPerSegment
= current
->Bcb
->CacheSegmentSize
/ PAGESIZE
;
132 Status
= CcRosFlushCacheSegment(current
);
133 current
->ReferenceCount
--;
134 ExReleaseFastMutex(¤t
->Lock
);
135 if (!NT_SUCCESS(Status
))
137 DPRINT1("CC: Failed to flush cache segment.\n");
139 (*Count
) += PagesPerSegment
;
140 Target
-= PagesPerSegment
;
142 ExAcquireFastMutex(&ViewLock
);
143 current_entry
= DirtySegmentListHead
.Flink
;
145 ExReleaseFastMutex(&ViewLock
);
146 DPRINT("CcRosTrimCache() finished\n");
147 return(STATUS_SUCCESS
);
151 CcRosTrimCache(ULONG Target
, ULONG Priority
, PULONG NrFreed
)
153 * FUNCTION: Try to free some memory from the file cache.
155 * Target - The number of pages to be freed.
156 * Priority - The priority of free (currently unused).
157 * NrFreed - Points to a variable where the number of pages
158 * actually freed is returned.
161 PLIST_ENTRY current_entry
;
162 PCACHE_SEGMENT current
;
163 ULONG PagesPerSegment
;
167 DPRINT("CcRosTrimCache(Target %d)\n", Target
);
171 ExAcquireFastMutex(&ViewLock
);
172 current_entry
= CacheSegmentLRUListHead
.Flink
;
173 while (current_entry
!= &CacheSegmentLRUListHead
&& Target
> 0)
175 current
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
,
176 CacheSegmentLRUListEntry
);
177 current_entry
= current_entry
->Flink
;
178 Locked
= ExTryToAcquireFastMutex(¤t
->Lock
);
183 if (current
->MappedCount
> 0 || current
->Dirty
||
184 current
->ReferenceCount
> 0)
186 ExReleaseFastMutex(¤t
->Lock
);
189 ExReleaseFastMutex(¤t
->Lock
);
190 DPRINT("current->Bcb->CacheSegmentSize %d\n",
191 current
->Bcb
->CacheSegmentSize
);
192 PagesPerSegment
= current
->Bcb
->CacheSegmentSize
/ PAGESIZE
;
193 CcRosInternalFreeCacheSegment(current
->Bcb
, current
);
194 DPRINT("CcRosTrimCache(): Freed %d\n", PagesPerSegment
);
195 PagesFreed
= min(PagesPerSegment
, Target
);
196 Target
= Target
- PagesFreed
;
197 (*NrFreed
) = (*NrFreed
) + PagesFreed
;
199 ExReleaseFastMutex(&ViewLock
);
200 DPRINT("CcRosTrimCache() finished\n");
201 return(STATUS_SUCCESS
);
205 CcRosReleaseCacheSegment(PBCB Bcb
,
206 PCACHE_SEGMENT CacheSeg
,
211 BOOLEAN WasDirty
= CacheSeg
->Dirty
;
213 DPRINT("CcReleaseCachePage(Bcb %x, CacheSeg %x, Valid %d)\n",
214 Bcb
, CacheSeg
, Valid
);
216 CacheSeg
->Valid
= Valid
;
217 CacheSeg
->Dirty
= CacheSeg
->Dirty
|| Dirty
;
220 CacheSeg
->MappedCount
++;
222 ExReleaseFastMutex(&CacheSeg
->Lock
);
223 ExAcquireFastMutex(&ViewLock
);
224 if (!WasDirty
&& CacheSeg
->Dirty
)
226 InsertTailList(&DirtySegmentListHead
, &CacheSeg
->DirtySegmentListEntry
);
228 RemoveEntryList(&CacheSeg
->CacheSegmentLRUListEntry
);
229 InsertTailList(&CacheSegmentLRUListHead
,
230 &CacheSeg
->CacheSegmentLRUListEntry
);
231 ExReleaseFastMutex(&ViewLock
);
232 InterlockedDecrement(&CacheSeg
->ReferenceCount
);
234 DPRINT("CcReleaseCachePage() finished\n");
236 return(STATUS_SUCCESS
);
239 PCACHE_SEGMENT
CcRosLookupCacheSegment(PBCB Bcb
, ULONG FileOffset
)
241 PLIST_ENTRY current_entry
;
242 PCACHE_SEGMENT current
;
245 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldIrql
);
246 current_entry
= Bcb
->BcbSegmentListHead
.Flink
;
247 while (current_entry
!= &Bcb
->BcbSegmentListHead
)
249 current
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
,
250 BcbSegmentListEntry
);
251 if (current
->FileOffset
<= FileOffset
&&
252 (current
->FileOffset
+ Bcb
->CacheSegmentSize
) > FileOffset
)
254 KeReleaseSpinLock(&Bcb
->BcbLock
, oldIrql
);
257 current_entry
= current_entry
->Flink
;
259 KeReleaseSpinLock(&Bcb
->BcbLock
, oldIrql
);
264 CcRosMarkDirtyCacheSegment(PBCB Bcb
, ULONG FileOffset
)
266 PCACHE_SEGMENT CacheSeg
;
268 ExAcquireFastMutex(&ViewLock
);
269 CacheSeg
= CcRosLookupCacheSegment(Bcb
, FileOffset
);
270 if (CacheSeg
== NULL
)
274 ExAcquireFastMutex(&CacheSeg
->Lock
);
275 if (!CacheSeg
->Dirty
)
277 InsertTailList(&DirtySegmentListHead
, &CacheSeg
->DirtySegmentListEntry
);
279 CacheSeg
->Dirty
= TRUE
;
280 ExReleaseFastMutex(&CacheSeg
->Lock
);
281 ExReleaseFastMutex(&ViewLock
);
282 return(STATUS_SUCCESS
);
286 CcRosSuggestFreeCacheSegment(PBCB Bcb
, ULONG FileOffset
, BOOLEAN NowDirty
)
288 PCACHE_SEGMENT CacheSeg
;
290 ExAcquireFastMutex(&ViewLock
);
291 CacheSeg
= CcRosLookupCacheSegment(Bcb
, FileOffset
);
292 if (CacheSeg
== NULL
)
296 ExAcquireFastMutex(&CacheSeg
->Lock
);
297 if (CacheSeg
->MappedCount
> 0)
301 CacheSeg
->Dirty
= CacheSeg
->Dirty
|| NowDirty
;
302 if (CacheSeg
->Dirty
|| CacheSeg
->ReferenceCount
> 0)
304 ExReleaseFastMutex(&CacheSeg
->Lock
);
305 ExReleaseFastMutex(&ViewLock
);
306 return(STATUS_UNSUCCESSFUL
);
308 ExReleaseFastMutex(&CacheSeg
->Lock
);
309 CcRosInternalFreeCacheSegment(CacheSeg
->Bcb
, CacheSeg
);
310 ExReleaseFastMutex(&ViewLock
);
311 return(STATUS_SUCCESS
);
315 CcRosUnmapCacheSegment(PBCB Bcb
, ULONG FileOffset
, BOOLEAN NowDirty
)
317 PCACHE_SEGMENT CacheSeg
;
319 ExAcquireFastMutex(&ViewLock
);
320 CacheSeg
= CcRosLookupCacheSegment(Bcb
, FileOffset
);
321 if (CacheSeg
== NULL
)
323 ExReleaseFastMutex(&ViewLock
);
324 return(STATUS_UNSUCCESSFUL
);
326 CacheSeg
->ReferenceCount
++;
327 ExReleaseFastMutex(&ViewLock
);
328 ExAcquireFastMutex(&CacheSeg
->Lock
);
329 CacheSeg
->MappedCount
--;
330 CacheSeg
->Dirty
= CacheSeg
->Dirty
|| NowDirty
;
331 CacheSeg
->ReferenceCount
--;
332 ExReleaseFastMutex(&CacheSeg
->Lock
);
333 return(STATUS_SUCCESS
);
337 CcRosCreateCacheSegment(PBCB Bcb
,
339 PCACHE_SEGMENT
* CacheSeg
,
343 PCACHE_SEGMENT current
;
347 current
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(CACHE_SEGMENT
),
350 MmLockAddressSpace(MmGetKernelAddressSpace());
351 current
->BaseAddress
= NULL
;
352 Status
= MmCreateMemoryArea(KernelMode
,
353 MmGetKernelAddressSpace(),
354 MEMORY_AREA_CACHE_SEGMENT
,
355 ¤t
->BaseAddress
,
356 Bcb
->CacheSegmentSize
,
358 (PMEMORY_AREA
*)¤t
->MemoryArea
,
360 if (!NT_SUCCESS(Status
))
362 MmUnlockAddressSpace(MmGetKernelAddressSpace());
365 MmUnlockAddressSpace(MmGetKernelAddressSpace());
366 current
->Valid
= FALSE
;
367 current
->Dirty
= FALSE
;
368 current
->FileOffset
= ROUND_DOWN(FileOffset
, Bcb
->CacheSegmentSize
);
370 current
->MappedCount
= 0;
371 ExInitializeFastMutex(¤t
->Lock
);
372 current
->ReferenceCount
= 1;
373 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldIrql
);
374 InsertTailList(&Bcb
->BcbSegmentListHead
, ¤t
->BcbSegmentListEntry
);
375 KeReleaseSpinLock(&Bcb
->BcbLock
, oldIrql
);
376 InsertTailList(&CacheSegmentListHead
, ¤t
->CacheSegmentListEntry
);
377 InsertTailList(&CacheSegmentLRUListHead
,
378 ¤t
->CacheSegmentLRUListEntry
);
379 current
->DirtySegmentListEntry
.Flink
=
380 current
->DirtySegmentListEntry
.Blink
= NULL
;
383 ExAcquireFastMutex(¤t
->Lock
);
385 ExReleaseFastMutex(&ViewLock
);
386 for (i
= 0; i
< (Bcb
->CacheSegmentSize
/ PAGESIZE
); i
++)
388 PHYSICAL_ADDRESS Page
;
390 Status
= MmRequestPageMemoryConsumer(MC_CACHE
, TRUE
, &Page
);
391 if (!NT_SUCCESS(Status
))
396 Status
= MmCreateVirtualMapping(NULL
,
397 current
->BaseAddress
+ (i
* PAGESIZE
),
401 if (!NT_SUCCESS(Status
))
407 return(STATUS_SUCCESS
);
411 CcRosGetCacheSegmentChain(PBCB Bcb
,
414 PCACHE_SEGMENT
* CacheSeg
)
416 PCACHE_SEGMENT current
;
418 PCACHE_SEGMENT
* CacheSegList
;
419 PCACHE_SEGMENT Previous
= NULL
;
421 Length
= ROUND_UP(Length
, Bcb
->CacheSegmentSize
);
423 CacheSegList
= alloca(sizeof(PCACHE_SEGMENT
) *
424 (Length
/ Bcb
->CacheSegmentSize
));
427 * Acquire the global lock.
429 ExAcquireFastMutex(&ViewLock
);
432 * Look for a cache segment already mapping the same data.
434 for (i
= 0; i
< (Length
/ Bcb
->CacheSegmentSize
); i
++)
436 ULONG CurrentOffset
= FileOffset
+ (i
* Bcb
->CacheSegmentSize
);
437 current
= CcRosLookupCacheSegment(Bcb
, CurrentOffset
);
441 * Make sure the cache segment can't go away outside of our control.
443 current
->ReferenceCount
++;
444 CacheSegList
[i
] = current
;
448 CcRosCreateCacheSegment(Bcb
, CurrentOffset
, ¤t
, FALSE
);
449 CacheSegList
[i
] = current
;
450 ExAcquireFastMutex(&ViewLock
);
453 ExReleaseFastMutex(&ViewLock
);
455 for (i
= 0; i
< (Length
/ Bcb
->CacheSegmentSize
); i
++)
457 ExAcquireFastMutex(&CacheSegList
[i
]->Lock
);
460 *CacheSeg
= CacheSegList
[i
];
461 Previous
= CacheSegList
[i
];
465 Previous
->NextInChain
= CacheSegList
[i
];
466 Previous
= CacheSegList
[i
];
469 Previous
->NextInChain
= NULL
;
471 return(STATUS_SUCCESS
);
475 CcRosGetCacheSegment(PBCB Bcb
,
480 PCACHE_SEGMENT
* CacheSeg
)
482 PCACHE_SEGMENT current
;
486 * Acquire the global lock.
488 ExAcquireFastMutex(&ViewLock
);
491 * Look for a cache segment already mapping the same data.
493 current
= CcRosLookupCacheSegment(Bcb
, FileOffset
);
497 * Make sure the cache segment can't go away outside of our control.
499 current
->ReferenceCount
++;
501 * Release the global lock and lock the cache segment.
503 ExReleaseFastMutex(&ViewLock
);
504 ExAcquireFastMutex(¤t
->Lock
);
506 * Return information about the segment to the caller.
508 *UptoDate
= current
->Valid
;
509 *BaseAddress
= current
->BaseAddress
;
510 DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress
);
512 *BaseOffset
= current
->FileOffset
;
513 return(STATUS_SUCCESS
);
517 * Otherwise create a new segment.
519 Status
= CcRosCreateCacheSegment(Bcb
, FileOffset
, ¤t
, TRUE
);
520 *UptoDate
= current
->Valid
;
521 *BaseAddress
= current
->BaseAddress
;
522 DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress
);
524 *BaseOffset
= current
->FileOffset
;
526 return(STATUS_SUCCESS
);
530 CcRosRequestCacheSegment(PBCB Bcb
,
534 PCACHE_SEGMENT
* CacheSeg
)
536 * FUNCTION: Request a page mapping for a BCB
541 if ((FileOffset
% Bcb
->CacheSegmentSize
) != 0)
543 CPRINT("Bad fileoffset %x should be multiple of %x",
544 FileOffset
, Bcb
->CacheSegmentSize
);
548 return(CcRosGetCacheSegment(Bcb
,
557 CcFreeCachePage(PVOID Context
, MEMORY_AREA
* MemoryArea
, PVOID Address
,
558 PHYSICAL_ADDRESS PhysAddr
, SWAPENTRY SwapEntry
, BOOLEAN Dirty
)
560 assert(SwapEntry
== 0);
561 if (PhysAddr
.QuadPart
!= 0)
563 MmReleasePageMemoryConsumer(MC_CACHE
, PhysAddr
);
568 CcRosInternalFreeCacheSegment(PBCB Bcb
, PCACHE_SEGMENT CacheSeg
)
570 * FUNCTION: Releases a cache segment associated with a BCB
573 DPRINT("Freeing cache segment %x\n", CacheSeg
);
574 RemoveEntryList(&CacheSeg
->CacheSegmentListEntry
);
575 RemoveEntryList(&CacheSeg
->CacheSegmentLRUListEntry
);
576 RemoveEntryList(&CacheSeg
->BcbSegmentListEntry
);
577 MmLockAddressSpace(MmGetKernelAddressSpace());
578 MmFreeMemoryArea(MmGetKernelAddressSpace(),
579 CacheSeg
->BaseAddress
,
580 Bcb
->CacheSegmentSize
,
583 MmUnlockAddressSpace(MmGetKernelAddressSpace());
584 ExFreePool(CacheSeg
);
585 return(STATUS_SUCCESS
);
589 CcRosFreeCacheSegment(PBCB Bcb
, PCACHE_SEGMENT CacheSeg
)
592 ExAcquireFastMutex(&ViewLock
);
593 Status
= CcRosInternalFreeCacheSegment(Bcb
, CacheSeg
);
594 ExReleaseFastMutex(&ViewLock
);
599 CcRosDeleteFileCache(PFILE_OBJECT FileObject
, PBCB Bcb
)
601 * FUNCTION: Releases the BCB associated with a file object
604 PLIST_ENTRY current_entry
;
605 PCACHE_SEGMENT current
;
608 DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n", Bcb
->FileObject
,
611 MmFreeSectionSegments(Bcb
->FileObject
);
614 * Write back dirty cache segments.
616 current_entry
= Bcb
->BcbSegmentListHead
.Flink
;
617 while (current_entry
!= &Bcb
->BcbSegmentListHead
)
620 CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
, BcbSegmentListEntry
);
623 Status
= WriteCacheSegment(current
);
624 if (!NT_SUCCESS(Status
))
626 DPRINT1("Failed to write cache segment (Status %X)\n", Status
);
628 ExAcquireFastMutex(&ViewLock
);
629 RemoveEntryList(¤t
->DirtySegmentListEntry
);
630 ExReleaseFastMutex(&ViewLock
);
632 current_entry
= current_entry
->Flink
;
636 * Release all cache segments.
638 current_entry
= Bcb
->BcbSegmentListHead
.Flink
;
639 while (current_entry
!= &Bcb
->BcbSegmentListHead
)
642 CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
, BcbSegmentListEntry
);
643 current_entry
= current_entry
->Flink
;
644 CcRosFreeCacheSegment(Bcb
, current
);
646 FileObject
->SectionObjectPointers
->SharedCacheMap
= NULL
;
647 ObDereferenceObject (Bcb
->FileObject
);
650 return(STATUS_SUCCESS
);
653 VOID
CcRosReferenceCache(PFILE_OBJECT FileObject
)
656 PBCB Bcb
= (PBCB
)FileObject
->SectionObjectPointers
->SharedCacheMap
;
657 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldIrql
);
659 KeReleaseSpinLock(&Bcb
->BcbLock
, oldIrql
);
662 VOID
CcRosDereferenceCache(PFILE_OBJECT FileObject
)
665 PBCB Bcb
= (PBCB
)FileObject
->SectionObjectPointers
->SharedCacheMap
;
666 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldIrql
);
668 KeReleaseSpinLock(&Bcb
->BcbLock
, oldIrql
);
669 if (Bcb
->RefCount
== 0)
671 CcRosDeleteFileCache(FileObject
, Bcb
);
676 CcRosReleaseFileCache(PFILE_OBJECT FileObject
, PBCB Bcb
)
678 * FUNCTION: Called by the file system when a handle to a file object
683 if (FileObject
->SectionObjectPointers
->SharedCacheMap
!= NULL
)
685 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldIrql
);
686 if (FileObject
->PrivateCacheMap
!= NULL
)
688 FileObject
->PrivateCacheMap
= NULL
;
691 KeReleaseSpinLock(&Bcb
->BcbLock
, oldIrql
);
692 if (Bcb
->RefCount
== 0)
694 CcRosDeleteFileCache(FileObject
, Bcb
);
697 return(STATUS_SUCCESS
);
701 CcRosInitializeFileCache(PFILE_OBJECT FileObject
,
703 ULONG CacheSegmentSize
)
705 * FUNCTION: Initializes a BCB for a file object
711 (*Bcb
) = ExAllocatePoolWithTag(NonPagedPool
, sizeof(BCB
), TAG_BCB
);
714 return(STATUS_UNSUCCESSFUL
);
717 ObReferenceObjectByPointer(FileObject
,
721 (*Bcb
)->FileObject
= FileObject
;
722 (*Bcb
)->CacheSegmentSize
= CacheSegmentSize
;
723 if (FileObject
->FsContext
)
725 (*Bcb
)->AllocationSize
=
726 ((REACTOS_COMMON_FCB_HEADER
*)FileObject
->FsContext
)->AllocationSize
;
728 ((REACTOS_COMMON_FCB_HEADER
*)FileObject
->FsContext
)->FileSize
;
730 KeInitializeSpinLock(&(*Bcb
)->BcbLock
);
731 InitializeListHead(&(*Bcb
)->BcbSegmentListHead
);
732 FileObject
->SectionObjectPointers
->SharedCacheMap
= *Bcb
;
734 KeAcquireSpinLock(&(*Bcb
)->BcbLock
, &oldIrql
);
735 if (FileObject
->PrivateCacheMap
== NULL
)
737 FileObject
->PrivateCacheMap
= *Bcb
;
740 KeReleaseSpinLock(&(*Bcb
)->BcbLock
, oldIrql
);
742 return(STATUS_SUCCESS
);
748 DPRINT("CcInitView()\n");
749 InitializeListHead(&CacheSegmentListHead
);
750 InitializeListHead(&DirtySegmentListHead
);
751 InitializeListHead(&CacheSegmentLRUListHead
);
752 ExInitializeFastMutex(&ViewLock
);
753 MmInitializeMemoryConsumer(MC_CACHE
, CcRosTrimCache
);
754 CcInitCacheZeroPage();