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