xref: /reactos/ntoskrnl/cache/cachesub.c (revision c2c66aff)
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