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 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(&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 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_DBGBREAK(); 135 return Result; 136 } 137 138 139 140 VOID 141 NTAPI 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 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 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 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 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 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 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