659022f81f8ec66d4dabfc142c9c5ad0904247fb
[reactos.git] / reactos / ntoskrnl / cc / view.c
1 /* $Id: view.c,v 1.7 2000/02/26 22:41:34 ea Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cc/view.c
6 * PURPOSE: Cache manager
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ddk/ntifs.h>
16 #include <internal/mm.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 /* FUNCTIONS *****************************************************************/
22
23 NTSTATUS STDCALL CcFlushCachePage(PCACHE_SEGMENT CacheSeg)
24 /*
25 * FUNCTION: Asks the FSD to flush the contents of the page back to disk
26 */
27 {
28 KeWaitForSingleObject(&CacheSeg->Lock,
29 Executive,
30 KernelMode,
31 FALSE,
32 NULL);
33 /* Build an IRP_MJ_WRITE and send it to the filesystem */
34 KeSetEvent(&CacheSeg->Lock, IO_NO_INCREMENT, 0);
35 return(STATUS_NOT_IMPLEMENTED);
36 }
37
38 NTSTATUS STDCALL CcReleaseCachePage(PBCB Bcb,
39 PCACHE_SEGMENT CacheSeg,
40 BOOLEAN Valid)
41 {
42 DPRINT("CcReleaseCachePage(Bcb %x, CacheSeg %x, Valid %d)\n",
43 Bcb, CacheSeg, Valid);
44
45 CacheSeg->ReferenceCount--;
46 CacheSeg->Valid = Valid;
47 KeSetEvent(&CacheSeg->Lock, IO_NO_INCREMENT, FALSE);
48
49 DPRINT("CcReleaseCachePage() finished\n");
50
51 return(STATUS_SUCCESS);
52 }
53
54 NTSTATUS STDCALL CcRequestCachePage(PBCB Bcb,
55 ULONG FileOffset,
56 PVOID* BaseAddress,
57 PBOOLEAN UptoDate,
58 PCACHE_SEGMENT* CacheSeg)
59 {
60 KIRQL oldirql;
61 PLIST_ENTRY current_entry;
62 PCACHE_SEGMENT current;
63
64 DPRINT("CcRequestCachePage(Bcb %x, FileOffset %x, BaseAddress %x, "
65 "UptoDate %x, CacheSeg %x)\n", Bcb, FileOffset, BaseAddress,
66 UptoDate, CacheSeg);
67
68 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
69
70 current_entry = Bcb->CacheSegmentListHead.Flink;
71 while (current_entry != &Bcb->CacheSegmentListHead)
72 {
73 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, ListEntry);
74 if (current->FileOffset == PAGE_ROUND_DOWN(FileOffset))
75 {
76 DPRINT("Found existing segment at %x\n", current);
77 current->ReferenceCount++;
78 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
79 DPRINT("Waiting for segment\n");
80 KeWaitForSingleObject(&current->Lock,
81 Executive,
82 KernelMode,
83 FALSE,
84 NULL);
85 *UptoDate = current->Valid;
86 *BaseAddress = current->BaseAddress;
87 *CacheSeg = current;
88 DPRINT("Returning %x (UptoDate %d)\n", current, current->Valid);
89 return(STATUS_SUCCESS);
90 }
91 current_entry = current_entry->Flink;
92 }
93
94 DPRINT("Creating new segment\n");
95
96 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
97
98 current = ExAllocatePool(NonPagedPool, sizeof(CACHE_SEGMENT));
99 current->BaseAddress = NULL;
100 MmCreateMemoryArea(KernelMode,
101 NULL,
102 MEMORY_AREA_CACHE_SEGMENT,
103 &current->BaseAddress,
104 CACHE_SEGMENT_SIZE,
105 PAGE_READWRITE,
106 (PMEMORY_AREA*)&current->MemoryArea);
107 CHECKPOINT;
108 current->Valid = FALSE;
109 current->FileOffset = PAGE_ROUND_DOWN(FileOffset);
110 current->Bcb = Bcb;
111 CHECKPOINT;
112 KeInitializeEvent(&current->Lock, SynchronizationEvent, FALSE);
113 current->ReferenceCount = 1;
114 CHECKPOINT;
115 InsertTailList(&Bcb->CacheSegmentListHead, &current->ListEntry);
116 CHECKPOINT;
117 *UptoDate = current->Valid;
118 *BaseAddress = current->BaseAddress;
119 *CacheSeg = current;
120 CHECKPOINT;
121 MmSetPage(NULL,
122 current->BaseAddress,
123 PAGE_READWRITE,
124 (ULONG)MmAllocPage());
125
126
127 DPRINT("Returning %x (BaseAddress %x)\n", current, *BaseAddress);
128
129 return(STATUS_SUCCESS);
130 }
131
132 NTSTATUS STDCALL CcFreeCacheSegment(PFILE_OBJECT FileObject,
133 PBCB Bcb,
134 PCACHE_SEGMENT CacheSeg)
135 {
136 MmFreeMemoryArea(NULL,
137 CacheSeg->BaseAddress,
138 CACHE_SEGMENT_SIZE,
139 TRUE);
140 ExFreePool(CacheSeg);
141 return(STATUS_SUCCESS);
142 }
143
144 NTSTATUS STDCALL CcReleaseFileCache(PFILE_OBJECT FileObject,
145 PBCB Bcb)
146 {
147 PLIST_ENTRY current_entry;
148 PCACHE_SEGMENT current;
149
150 DPRINT("CcReleaseFileCache(FileObject %x, Bcb %x)\n",
151 FileObject, Bcb);
152
153 current_entry = Bcb->CacheSegmentListHead.Flink;
154 while (current_entry != (&Bcb->CacheSegmentListHead))
155 {
156 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, ListEntry);
157 current_entry = current_entry->Flink;
158 CcFreeCacheSegment(FileObject,
159 Bcb,
160 current);
161 }
162
163 ExFreePool(Bcb);
164
165 DPRINT("CcReleaseFileCache() finished\n");
166
167 return(STATUS_SUCCESS);
168 }
169
170 NTSTATUS STDCALL CcInitializeFileCache(PFILE_OBJECT FileObject,
171 PBCB* Bcb)
172 {
173 DPRINT("CcInitializeFileCache(FileObject %x)\n",FileObject);
174
175 (*Bcb) = ExAllocatePool(NonPagedPool, sizeof(BCB));
176 if ((*Bcb) == NULL)
177 {
178 return(STATUS_UNSUCCESSFUL);
179 }
180
181 (*Bcb)->FileObject = FileObject;
182 InitializeListHead(&(*Bcb)->CacheSegmentListHead);
183 KeInitializeSpinLock(&(*Bcb)->BcbLock);
184
185 DPRINT("Finished CcInitializeFileCache() = %x\n", *Bcb);
186
187 return(STATUS_SUCCESS);
188 }
189
190
191 /* EOF */