1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/cc/pin.c 5 * PURPOSE: Implements cache managers pinning interface 6 * 7 * PROGRAMMERS: ? 8 Pierre Schweitzer (pierre@reactos.org) 9 */ 10 11 /* INCLUDES ******************************************************************/ 12 13 #include <ntoskrnl.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS *******************************************************************/ 18 19 extern NPAGED_LOOKASIDE_LIST iBcbLookasideList; 20 21 /* Counters: 22 * - Number of calls to CcMapData that could wait 23 * - Number of calls to CcMapData that couldn't wait 24 * - Number of calls to CcPinRead that could wait 25 * - Number of calls to CcPinRead that couldn't wait 26 */ 27 ULONG CcMapDataWait = 0; 28 ULONG CcMapDataNoWait = 0; 29 ULONG CcPinReadWait = 0; 30 ULONG CcPinReadNoWait = 0; 31 32 /* FUNCTIONS *****************************************************************/ 33 34 /* 35 * @implemented 36 */ 37 BOOLEAN 38 NTAPI 39 CcMapData ( 40 IN PFILE_OBJECT FileObject, 41 IN PLARGE_INTEGER FileOffset, 42 IN ULONG Length, 43 IN ULONG Flags, 44 OUT PVOID *pBcb, 45 OUT PVOID *pBuffer) 46 { 47 LONGLONG ReadOffset; 48 BOOLEAN Valid; 49 PROS_SHARED_CACHE_MAP SharedCacheMap; 50 PROS_VACB Vacb; 51 NTSTATUS Status; 52 PINTERNAL_BCB iBcb; 53 LONGLONG ROffset; 54 55 DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx," 56 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart, 57 Length, Flags, pBcb, pBuffer); 58 59 if (Flags & MAP_WAIT) 60 { 61 ++CcMapDataWait; 62 } 63 else 64 { 65 ++CcMapDataNoWait; 66 } 67 68 ReadOffset = FileOffset->QuadPart; 69 70 ASSERT(FileObject); 71 ASSERT(FileObject->SectionObjectPointer); 72 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap); 73 74 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 75 ASSERT(SharedCacheMap); 76 77 DPRINT("SectionSize %I64x, FileSize %I64x\n", 78 SharedCacheMap->SectionSize.QuadPart, 79 SharedCacheMap->FileSize.QuadPart); 80 81 if (ReadOffset % VACB_MAPPING_GRANULARITY + Length > VACB_MAPPING_GRANULARITY) 82 { 83 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 84 FileObject, FileOffset, Length, Flags); 85 ExRaiseStatus(STATUS_INVALID_PARAMETER); 86 return FALSE; 87 } 88 89 ROffset = ROUND_DOWN(ReadOffset, VACB_MAPPING_GRANULARITY); 90 Status = CcRosRequestVacb(SharedCacheMap, 91 ROffset, 92 pBuffer, 93 &Valid, 94 &Vacb); 95 if (!NT_SUCCESS(Status)) 96 { 97 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 98 FileObject, FileOffset, Length, Flags); 99 ExRaiseStatus(Status); 100 return FALSE; 101 } 102 103 if (!Valid) 104 { 105 if (!(Flags & MAP_WAIT)) 106 { 107 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE); 108 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 109 FileObject, FileOffset, Length, Flags); 110 return FALSE; 111 } 112 113 Status = CcReadVirtualAddress(Vacb); 114 if (!NT_SUCCESS(Status)) 115 { 116 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE); 117 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 118 FileObject, FileOffset, Length, Flags); 119 ExRaiseStatus(Status); 120 return FALSE; 121 } 122 } 123 124 *pBuffer = (PUCHAR)*pBuffer + ReadOffset % VACB_MAPPING_GRANULARITY; 125 iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList); 126 if (iBcb == NULL) 127 { 128 CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE); 129 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 130 FileObject, FileOffset, Length, Flags); 131 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 132 return FALSE; 133 } 134 135 RtlZeroMemory(iBcb, sizeof(*iBcb)); 136 iBcb->PFCB.NodeTypeCode = 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */ 137 iBcb->PFCB.NodeByteSize = sizeof(PUBLIC_BCB); 138 iBcb->PFCB.MappedLength = Length; 139 iBcb->PFCB.MappedFileOffset = *FileOffset; 140 iBcb->Vacb = Vacb; 141 iBcb->Dirty = FALSE; 142 iBcb->Pinned = FALSE; 143 iBcb->RefCount = 1; 144 ExInitializeResourceLite(&iBcb->Lock); 145 *pBcb = (PVOID)iBcb; 146 147 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p\n", 148 FileObject, FileOffset, Length, Flags, iBcb); 149 return TRUE; 150 } 151 152 /* 153 * @unimplemented 154 */ 155 BOOLEAN 156 NTAPI 157 CcPinMappedData ( 158 IN PFILE_OBJECT FileObject, 159 IN PLARGE_INTEGER FileOffset, 160 IN ULONG Length, 161 IN ULONG Flags, 162 OUT PVOID * Bcb) 163 { 164 PROS_SHARED_CACHE_MAP SharedCacheMap; 165 166 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n", 167 FileObject, FileOffset, Length, Flags); 168 169 ASSERT(FileObject); 170 ASSERT(FileObject->SectionObjectPointer); 171 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap); 172 173 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 174 ASSERT(SharedCacheMap); 175 ASSERT(SharedCacheMap->PinAccess); 176 177 /* no-op for current implementation. */ 178 return TRUE; 179 } 180 181 /* 182 * @unimplemented 183 */ 184 BOOLEAN 185 NTAPI 186 CcPinRead ( 187 IN PFILE_OBJECT FileObject, 188 IN PLARGE_INTEGER FileOffset, 189 IN ULONG Length, 190 IN ULONG Flags, 191 OUT PVOID * Bcb, 192 OUT PVOID * Buffer) 193 { 194 PINTERNAL_BCB iBcb; 195 196 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n", 197 FileObject, FileOffset, Length, Flags); 198 199 if (Flags & PIN_WAIT) 200 { 201 ++CcPinReadWait; 202 } 203 else 204 { 205 ++CcPinReadNoWait; 206 } 207 208 if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer)) 209 { 210 if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb)) 211 { 212 iBcb = *Bcb; 213 214 ASSERT(iBcb->Pinned == FALSE); 215 216 iBcb->Pinned = TRUE; 217 iBcb->Vacb->PinCount++; 218 CcRosReleaseVacbLock(iBcb->Vacb); 219 220 if (Flags & PIN_EXCLUSIVE) 221 { 222 ExAcquireResourceExclusiveLite(&iBcb->Lock, TRUE); 223 } 224 else 225 { 226 ExAcquireResourceSharedLite(&iBcb->Lock, TRUE); 227 } 228 229 return TRUE; 230 } 231 else 232 CcUnpinData(*Bcb); 233 } 234 return FALSE; 235 } 236 237 /* 238 * @unimplemented 239 */ 240 BOOLEAN 241 NTAPI 242 CcPreparePinWrite ( 243 IN PFILE_OBJECT FileObject, 244 IN PLARGE_INTEGER FileOffset, 245 IN ULONG Length, 246 IN BOOLEAN Zero, 247 IN ULONG Flags, 248 OUT PVOID * Bcb, 249 OUT PVOID * Buffer) 250 { 251 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n", 252 FileObject, FileOffset, Length, Zero, Flags); 253 254 /* 255 * FIXME: This is function is similar to CcPinRead, but doesn't 256 * read the data if they're not present. Instead it should just 257 * prepare the VACBs and zero them out if Zero != FALSE. 258 * 259 * For now calling CcPinRead is better than returning error or 260 * just having UNIMPLEMENTED here. 261 */ 262 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer); 263 } 264 265 /* 266 * @implemented 267 */ 268 VOID NTAPI 269 CcSetDirtyPinnedData ( 270 IN PVOID Bcb, 271 IN PLARGE_INTEGER Lsn) 272 { 273 PINTERNAL_BCB iBcb = Bcb; 274 275 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", 276 Bcb, Lsn); 277 278 iBcb->Dirty = TRUE; 279 } 280 281 282 /* 283 * @implemented 284 */ 285 VOID NTAPI 286 CcUnpinData ( 287 IN PVOID Bcb) 288 { 289 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb); 290 291 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread()); 292 } 293 294 /* 295 * @unimplemented 296 */ 297 VOID 298 NTAPI 299 CcUnpinDataForThread ( 300 IN PVOID Bcb, 301 IN ERESOURCE_THREAD ResourceThreadId) 302 { 303 PINTERNAL_BCB iBcb = Bcb; 304 305 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId); 306 307 if (iBcb->Pinned) 308 { 309 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId); 310 iBcb->Pinned = FALSE; 311 CcRosAcquireVacbLock(iBcb->Vacb, NULL); 312 iBcb->Vacb->PinCount--; 313 } 314 315 if (--iBcb->RefCount == 0) 316 { 317 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap, 318 iBcb->Vacb, 319 TRUE, 320 iBcb->Dirty, 321 FALSE); 322 323 ExDeleteResourceLite(&iBcb->Lock); 324 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 325 } 326 } 327 328 /* 329 * @implemented 330 */ 331 VOID 332 NTAPI 333 CcRepinBcb ( 334 IN PVOID Bcb) 335 { 336 PINTERNAL_BCB iBcb = Bcb; 337 338 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb); 339 340 iBcb->RefCount++; 341 } 342 343 /* 344 * @unimplemented 345 */ 346 VOID 347 NTAPI 348 CcUnpinRepinnedBcb ( 349 IN PVOID Bcb, 350 IN BOOLEAN WriteThrough, 351 IN PIO_STATUS_BLOCK IoStatus) 352 { 353 PINTERNAL_BCB iBcb = Bcb; 354 355 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough); 356 357 IoStatus->Status = STATUS_SUCCESS; 358 if (--iBcb->RefCount == 0) 359 { 360 IoStatus->Information = 0; 361 if (WriteThrough) 362 { 363 CcRosAcquireVacbLock(iBcb->Vacb, NULL); 364 if (iBcb->Vacb->Dirty) 365 { 366 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb); 367 } 368 else 369 { 370 IoStatus->Status = STATUS_SUCCESS; 371 } 372 CcRosReleaseVacbLock(iBcb->Vacb); 373 } 374 else 375 { 376 IoStatus->Status = STATUS_SUCCESS; 377 } 378 379 if (iBcb->Pinned) 380 { 381 ExReleaseResourceLite(&iBcb->Lock); 382 iBcb->Pinned = FALSE; 383 CcRosAcquireVacbLock(iBcb->Vacb, NULL); 384 iBcb->Vacb->PinCount--; 385 ASSERT(iBcb->Vacb->PinCount == 0); 386 } 387 388 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap, 389 iBcb->Vacb, 390 TRUE, 391 iBcb->Dirty, 392 FALSE); 393 394 ExDeleteResourceLite(&iBcb->Lock); 395 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 396 } 397 } 398