[CLT2012]
[reactos.git] / ntoskrnl / cache / cachesub.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/cache/cachesup.c
5 * PURPOSE: Logging and configuration routines
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Art Yerkes
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #include "newcc.h"
14 #include "section/newmm.h"
15 #define NDEBUG
16 #include <debug.h>
17
18 /* STRUCTURES *****************************************************************/
19
20 typedef struct _WORK_QUEUE_WITH_READ_AHEAD
21 {
22 WORK_QUEUE_ITEM WorkItem;
23 PFILE_OBJECT FileObject;
24 LARGE_INTEGER FileOffset;
25 ULONG Length;
26 } WORK_QUEUE_WITH_READ_AHEAD, *PWORK_QUEUE_WITH_READ_AHEAD;
27
28 /* FUNCTIONS ******************************************************************/
29
30 PDEVICE_OBJECT
31 NTAPI
32 MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject);
33
34 VOID
35 NTAPI
36 CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject,
37 IN ULONG Granularity)
38 {
39 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
40 if (Map)
41 {
42 Map->ReadAheadGranularity = Granularity;
43 }
44 }
45 \f
46 VOID
47 NTAPI
48 CcpReadAhead(PVOID Context)
49 {
50 LARGE_INTEGER Offset;
51 PWORK_QUEUE_WITH_READ_AHEAD WorkItem = (PWORK_QUEUE_WITH_READ_AHEAD)Context;
52 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)WorkItem->FileObject->SectionObjectPointer->SharedCacheMap;
53 DPRINT("Reading ahead %08x%08x:%x %wZ\n",
54 WorkItem->FileOffset.HighPart,
55 WorkItem->FileOffset.LowPart,
56 WorkItem->Length,
57 &WorkItem->FileObject->FileName);
58 Offset.HighPart = WorkItem->FileOffset.HighPart;
59 Offset.LowPart = PAGE_ROUND_DOWN(WorkItem->FileOffset.LowPart);
60 if (Map)
61 {
62 PLIST_ENTRY ListEntry;
63 volatile char *chptr;
64 PNOCC_BCB Bcb;
65 for (ListEntry = Map->AssociatedBcb.Flink;
66 ListEntry != &Map->AssociatedBcb;
67 ListEntry = ListEntry->Flink)
68 {
69 Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList);
70 if ((Offset.QuadPart + WorkItem->Length < Bcb->FileOffset.QuadPart) ||
71 (Bcb->FileOffset.QuadPart + Bcb->Length < Offset.QuadPart))
72 continue;
73 for (chptr = Bcb->BaseAddress, Offset = Bcb->FileOffset;
74 chptr < ((PCHAR)Bcb->BaseAddress) + Bcb->Length &&
75 Offset.QuadPart <
76 WorkItem->FileOffset.QuadPart + WorkItem->Length;
77 chptr += PAGE_SIZE, Offset.QuadPart += PAGE_SIZE)
78 {
79 *chptr ^= 0;
80 }
81 }
82 }
83 ObDereferenceObject(WorkItem->FileObject);
84 ExFreePool(WorkItem);
85 DPRINT("Done\n");
86 }
87
88 VOID
89 NTAPI
90 CcScheduleReadAhead(IN PFILE_OBJECT FileObject,
91 IN PLARGE_INTEGER FileOffset,
92 IN ULONG Length)
93 {
94 PWORK_QUEUE_WITH_READ_AHEAD WorkItem;
95 DPRINT("Schedule read ahead %08x%08x:%x %wZ\n",
96 FileOffset->HighPart,
97 FileOffset->LowPart,
98 Length,
99 &FileObject->FileName);
100 WorkItem = ExAllocatePool(NonPagedPool, sizeof(*WorkItem));
101 if (!WorkItem) KeBugCheck(0);
102 ObReferenceObject(FileObject);
103 WorkItem->FileObject = FileObject;
104 WorkItem->FileOffset = *FileOffset;
105 WorkItem->Length = Length;
106 ExInitializeWorkItem(((PWORK_QUEUE_ITEM)WorkItem), (PWORKER_THREAD_ROUTINE)CcpReadAhead, WorkItem);
107 ExQueueWorkItem((PWORK_QUEUE_ITEM)WorkItem, DelayedWorkQueue);
108 DPRINT("Done\n");
109 }
110 \f
111 VOID
112 NTAPI
113 CcSetDirtyPinnedData(IN PVOID BcbVoid,
114 IN OPTIONAL PLARGE_INTEGER Lsn)
115 {
116 PNOCC_BCB Bcb = (PNOCC_BCB)BcbVoid;
117 Bcb->Dirty = TRUE;
118 }
119
120 LARGE_INTEGER
121 NTAPI
122 CcGetFlushedValidData(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
123 IN BOOLEAN CcInternalCaller)
124 {
125 LARGE_INTEGER Result = {{0}};
126 UNIMPLEMENTED;
127 while (TRUE);
128 return Result;
129 }
130
131 \f
132
133 VOID
134 NTAPI
135 _CcpFlushCache(IN PNOCC_CACHE_MAP Map,
136 IN OPTIONAL PLARGE_INTEGER FileOffset,
137 IN ULONG Length,
138 OUT OPTIONAL PIO_STATUS_BLOCK IoStatus,
139 BOOLEAN Delete,
140 const char *File,
141 int Line)
142 {
143 PNOCC_BCB Bcb = NULL;
144 LARGE_INTEGER LowerBound, UpperBound;
145 PLIST_ENTRY ListEntry;
146 IO_STATUS_BLOCK IOSB = { };
147
148 DPRINT1("CcFlushCache (while file) (%s:%d)\n", File, Line);
149
150 if (FileOffset && Length)
151 {
152 LowerBound.QuadPart = FileOffset->QuadPart;
153 UpperBound.QuadPart = LowerBound.QuadPart + Length;
154 }
155 else
156 {
157 LowerBound.QuadPart = 0;
158 UpperBound.QuadPart = 0x7fffffffffffffffull;
159 }
160
161 CcpLock();
162 ListEntry = Map->AssociatedBcb.Flink;
163
164 while (ListEntry != &Map->AssociatedBcb)
165 {
166 Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList);
167 CcpReferenceCache(Bcb - CcCacheSections);
168
169 if (Bcb->FileOffset.QuadPart + Bcb->Length >= LowerBound.QuadPart &&
170 Bcb->FileOffset.QuadPart < UpperBound.QuadPart)
171 {
172 DPRINT
173 ("Bcb #%x (@%08x%08x)\n",
174 Bcb - CcCacheSections,
175 Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart);
176
177 Bcb->RefCount++;
178 CcpUnlock();
179 MiFlushMappedSection(Bcb->BaseAddress, &Bcb->FileOffset, &Map->FileSizes.FileSize, Bcb->Dirty);
180 CcpLock();
181 Bcb->RefCount--;
182
183 Bcb->Dirty = FALSE;
184
185 ListEntry = ListEntry->Flink;
186 if (Delete && Bcb->RefCount < 2)
187 {
188 Bcb->RefCount = 1;
189 CcpDereferenceCache(Bcb - CcCacheSections, FALSE);
190 }
191 else
192 CcpUnpinData(Bcb, TRUE);
193 }
194 else
195 {
196 ListEntry = ListEntry->Flink;
197 CcpUnpinData(Bcb, TRUE);
198 }
199
200 DPRINT("End loop\n");
201 }
202 CcpUnlock();
203
204 if (IoStatus) *IoStatus = IOSB;
205 }
206
207 VOID
208 NTAPI
209 CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
210 IN OPTIONAL PLARGE_INTEGER FileOffset,
211 IN ULONG Length,
212 OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
213 {
214 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
215
216 // Not cached
217 if (!Map)
218 {
219 if (IoStatus)
220 {
221 IoStatus->Status = STATUS_SUCCESS;
222 IoStatus->Information = 0;
223 }
224 return;
225 }
226
227 CcpFlushCache(Map, FileOffset, Length, IoStatus, TRUE);
228 }
229
230 BOOLEAN
231 NTAPI
232 CcFlushImageSection
233 (PSECTION_OBJECT_POINTERS SectionObjectPointer,
234 MMFLUSH_TYPE FlushType)
235 {
236 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
237 PNOCC_BCB Bcb;
238 PLIST_ENTRY Entry;
239 IO_STATUS_BLOCK IOSB;
240 BOOLEAN Result = TRUE;
241
242 if (!Map) return TRUE;
243
244 for (Entry = Map->AssociatedBcb.Flink;
245 Entry != &Map->AssociatedBcb;
246 Entry = Entry->Flink)
247 {
248 Bcb = CONTAINING_RECORD(Entry, NOCC_BCB, ThisFileList);
249
250 if (!Bcb->Dirty) continue;
251
252 switch (FlushType)
253 {
254 case MmFlushForDelete:
255 CcPurgeCacheSection
256 (SectionObjectPointer,
257 &Bcb->FileOffset,
258 Bcb->Length,
259 FALSE);
260 break;
261 case MmFlushForWrite:
262 CcFlushCache
263 (SectionObjectPointer,
264 &Bcb->FileOffset,
265 Bcb->Length,
266 &IOSB);
267 break;
268 }
269 }
270
271 return Result;
272 }
273
274 // Always succeeds for us
275 PVOID
276 NTAPI
277 CcRemapBcb(IN PVOID Bcb)
278 {
279 CcpLock();
280 ASSERT(RtlTestBit(CcCacheBitmap, ((PNOCC_BCB)Bcb) - CcCacheSections));
281 CcpReferenceCache(((PNOCC_BCB)Bcb) - CcCacheSections);
282 CcpUnlock();
283 return Bcb;
284 }
285
286 VOID
287 NTAPI
288 CcShutdownSystem()
289 {
290 ULONG i;
291
292 DPRINT1("CC: Shutdown\n");
293
294 for (i = 0; i < CACHE_NUM_SECTIONS; i++)
295 {
296 PNOCC_BCB Bcb = &CcCacheSections[i];
297 if (Bcb->SectionObject)
298 {
299 DPRINT1
300 ("Evicting #%02x %08x%08x %wZ\n",
301 i,
302 Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart,
303 &MmGetFileObjectForSection
304 ((PROS_SECTION_OBJECT)Bcb->SectionObject)->FileName);
305 CcpFlushCache(Bcb->Map, NULL, 0, NULL, TRUE);
306 Bcb->Dirty = FALSE;
307 }
308 }
309
310 DPRINT1("Done\n");
311 }
312
313 \f
314 VOID
315 NTAPI
316 CcRepinBcb(IN PVOID Bcb)
317 {
318 CcpLock();
319 ASSERT(RtlTestBit(CcCacheBitmap, ((PNOCC_BCB)Bcb) - CcCacheSections));
320 DPRINT("CcRepinBcb(#%x)\n", ((PNOCC_BCB)Bcb) - CcCacheSections);
321 CcpReferenceCache(((PNOCC_BCB)Bcb) - CcCacheSections);
322 CcpUnlock();
323 }
324
325 VOID
326 NTAPI
327 CcUnpinRepinnedBcb(IN PVOID Bcb,
328 IN BOOLEAN WriteThrough,
329 OUT PIO_STATUS_BLOCK IoStatus)
330 {
331 PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb;
332
333 if (WriteThrough)
334 {
335 DPRINT("BCB #%x\n", RealBcb - CcCacheSections);
336
337 CcpFlushCache
338 (RealBcb->Map,
339 &RealBcb->FileOffset,
340 RealBcb->Length,
341 IoStatus, RealBcb->Dirty);
342 }
343
344 CcUnpinData(Bcb);
345 }
346
347 /* EOF */