Create a branch for working on csrss and co.
[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
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
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
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(((PWORK_QUEUE_ITEM)WorkItem),
112 (PWORKER_THREAD_ROUTINE)CcpReadAhead,
113 WorkItem);
114
115 ExQueueWorkItem((PWORK_QUEUE_ITEM)WorkItem, DelayedWorkQueue);
116 DPRINT("Done\n");
117 }
118
119 VOID
120 NTAPI
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
130 CcGetFlushedValidData(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
131 IN BOOLEAN CcInternalCaller)
132 {
133 LARGE_INTEGER Result = {{0}};
134 UNIMPLEMENTED;
135 while (TRUE);
136 return Result;
137 }
138
139
140
141 VOID
142 NTAPI
143 _CcpFlushCache(IN PNOCC_CACHE_MAP Map,
144 IN OPTIONAL PLARGE_INTEGER FileOffset,
145 IN ULONG Length,
146 OUT OPTIONAL PIO_STATUS_BLOCK IoStatus,
147 BOOLEAN Delete,
148 const char *File,
149 int Line)
150 {
151 PNOCC_BCB Bcb = NULL;
152 LARGE_INTEGER LowerBound, UpperBound;
153 PLIST_ENTRY ListEntry;
154 IO_STATUS_BLOCK IOSB;
155
156 RtlZeroMemory(&IOSB, sizeof(IO_STATUS_BLOCK));
157
158 DPRINT("CcFlushCache (while file) (%s:%d)\n", File, Line);
159
160 if (FileOffset && Length)
161 {
162 LowerBound.QuadPart = FileOffset->QuadPart;
163 UpperBound.QuadPart = LowerBound.QuadPart + Length;
164 }
165 else
166 {
167 LowerBound.QuadPart = 0;
168 UpperBound.QuadPart = 0x7fffffffffffffffull;
169 }
170
171 CcpLock();
172 ListEntry = Map->AssociatedBcb.Flink;
173
174 while (ListEntry != &Map->AssociatedBcb)
175 {
176 Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList);
177 CcpReferenceCache((ULONG)(Bcb - CcCacheSections));
178
179 if (Bcb->FileOffset.QuadPart + Bcb->Length >= LowerBound.QuadPart &&
180 Bcb->FileOffset.QuadPart < UpperBound.QuadPart)
181 {
182 DPRINT("Bcb #%x (@%08x%08x)\n",
183 Bcb - CcCacheSections,
184 Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart);
185
186 Bcb->RefCount++;
187 CcpUnlock();
188 MiFlushMappedSection(Bcb->BaseAddress,
189 &Bcb->FileOffset,
190 &Map->FileSizes.FileSize,
191 Bcb->Dirty);
192 CcpLock();
193 Bcb->RefCount--;
194
195 Bcb->Dirty = FALSE;
196
197 ListEntry = ListEntry->Flink;
198 if (Delete && Bcb->RefCount < 2)
199 {
200 Bcb->RefCount = 1;
201 CcpDereferenceCache((ULONG)(Bcb - CcCacheSections), FALSE);
202 }
203 else
204 {
205 CcpUnpinData(Bcb, TRUE);
206 }
207 }
208 else
209 {
210 ListEntry = ListEntry->Flink;
211 CcpUnpinData(Bcb, TRUE);
212 }
213
214 DPRINT("End loop\n");
215 }
216 CcpUnlock();
217
218 if (IoStatus) *IoStatus = IOSB;
219 }
220
221 VOID
222 NTAPI
223 CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
224 IN OPTIONAL PLARGE_INTEGER FileOffset,
225 IN ULONG Length,
226 OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
227 {
228 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
229
230 /* Not cached */
231 if (!Map)
232 {
233 if (IoStatus)
234 {
235 IoStatus->Status = STATUS_SUCCESS;
236 IoStatus->Information = 0;
237 }
238 return;
239 }
240
241 CcpFlushCache(Map, FileOffset, Length, IoStatus, TRUE);
242 }
243
244 BOOLEAN
245 NTAPI
246 CcFlushImageSection(PSECTION_OBJECT_POINTERS SectionObjectPointer,
247 MMFLUSH_TYPE FlushType)
248 {
249 PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
250 PNOCC_BCB Bcb;
251 PLIST_ENTRY Entry;
252 IO_STATUS_BLOCK IOSB;
253 BOOLEAN Result = TRUE;
254
255 if (!Map) return TRUE;
256
257 for (Entry = Map->AssociatedBcb.Flink;
258 Entry != &Map->AssociatedBcb;
259 Entry = Entry->Flink)
260 {
261 Bcb = CONTAINING_RECORD(Entry, NOCC_BCB, ThisFileList);
262
263 if (!Bcb->Dirty) continue;
264
265 switch (FlushType)
266 {
267 case MmFlushForDelete:
268 CcPurgeCacheSection(SectionObjectPointer,
269 &Bcb->FileOffset,
270 Bcb->Length,
271 FALSE);
272 break;
273 case MmFlushForWrite:
274 CcFlushCache(SectionObjectPointer,
275 &Bcb->FileOffset,
276 Bcb->Length,
277 &IOSB);
278 break;
279 }
280 }
281
282 return Result;
283 }
284
285 /* Always succeeds for us */
286 PVOID
287 NTAPI
288 CcRemapBcb(IN PVOID Bcb)
289 {
290 ULONG Number = (ULONG)(((PNOCC_BCB)Bcb) - CcCacheSections);
291 CcpLock();
292 ASSERT(RtlTestBit(CcCacheBitmap, Number));
293 CcpReferenceCache(Number);
294 CcpUnlock();
295 return Bcb;
296 }
297
298 VOID
299 NTAPI
300 CcShutdownSystem(VOID)
301 {
302 ULONG i, Result;
303 NTSTATUS Status;
304
305 DPRINT1("CC: Shutdown\n");
306
307 for (i = 0; i < CACHE_NUM_SECTIONS; i++)
308 {
309 PNOCC_BCB Bcb = &CcCacheSections[i];
310 if (Bcb->SectionObject)
311 {
312 DPRINT1("Evicting #%02x %08x%08x %wZ\n",
313 i,
314 Bcb->FileOffset.u.HighPart,
315 Bcb->FileOffset.u.LowPart,
316 &MmGetFileObjectForSection((PROS_SECTION_OBJECT)Bcb->SectionObject)->FileName);
317
318 CcpFlushCache(Bcb->Map, NULL, 0, NULL, TRUE);
319 Bcb->Dirty = FALSE;
320 }
321 }
322
323 /* Evict all section pages */
324 Status = MiRosTrimCache(~0, 0, &Result);
325
326 DPRINT1("Done (Evicted %d, Status %x)\n", Result, Status);
327 }
328
329
330 VOID
331 NTAPI
332 CcRepinBcb(IN PVOID Bcb)
333 {
334 ULONG Number = (ULONG)(((PNOCC_BCB)Bcb) - CcCacheSections);
335 CcpLock();
336 ASSERT(RtlTestBit(CcCacheBitmap, Number));
337 DPRINT("CcRepinBcb(#%x)\n", Number);
338 CcpReferenceCache(Number);
339 CcpUnlock();
340 }
341
342 VOID
343 NTAPI
344 CcUnpinRepinnedBcb(IN PVOID Bcb,
345 IN BOOLEAN WriteThrough,
346 OUT PIO_STATUS_BLOCK IoStatus)
347 {
348 PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb;
349
350 if (WriteThrough)
351 {
352 DPRINT("BCB #%x\n", RealBcb - CcCacheSections);
353
354 CcpFlushCache(RealBcb->Map,
355 &RealBcb->FileOffset,
356 RealBcb->Length,
357 IoStatus,
358 RealBcb->Dirty);
359 }
360
361 CcUnpinData(Bcb);
362 }
363
364 /* EOF */