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 219 if (Flags & PIN_EXCLUSIVE) 220 { 221 ExAcquireResourceExclusiveLite(&iBcb->Lock, TRUE); 222 } 223 else 224 { 225 ExAcquireResourceSharedLite(&iBcb->Lock, TRUE); 226 } 227 228 return TRUE; 229 } 230 else 231 CcUnpinData(*Bcb); 232 } 233 return FALSE; 234 } 235 236 /* 237 * @unimplemented 238 */ 239 BOOLEAN 240 NTAPI 241 CcPreparePinWrite ( 242 IN PFILE_OBJECT FileObject, 243 IN PLARGE_INTEGER FileOffset, 244 IN ULONG Length, 245 IN BOOLEAN Zero, 246 IN ULONG Flags, 247 OUT PVOID * Bcb, 248 OUT PVOID * Buffer) 249 { 250 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n", 251 FileObject, FileOffset, Length, Zero, Flags); 252 253 /* 254 * FIXME: This is function is similar to CcPinRead, but doesn't 255 * read the data if they're not present. Instead it should just 256 * prepare the VACBs and zero them out if Zero != FALSE. 257 * 258 * For now calling CcPinRead is better than returning error or 259 * just having UNIMPLEMENTED here. 260 */ 261 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer); 262 } 263 264 /* 265 * @implemented 266 */ 267 VOID NTAPI 268 CcSetDirtyPinnedData ( 269 IN PVOID Bcb, 270 IN PLARGE_INTEGER Lsn) 271 { 272 PINTERNAL_BCB iBcb = Bcb; 273 274 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", 275 Bcb, Lsn); 276 277 iBcb->Dirty = TRUE; 278 if (!iBcb->Vacb->Dirty) 279 { 280 CcRosMarkDirtyVacb(iBcb->Vacb); 281 } 282 } 283 284 285 /* 286 * @implemented 287 */ 288 VOID NTAPI 289 CcUnpinData ( 290 IN PVOID Bcb) 291 { 292 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb); 293 294 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread()); 295 } 296 297 /* 298 * @unimplemented 299 */ 300 VOID 301 NTAPI 302 CcUnpinDataForThread ( 303 IN PVOID Bcb, 304 IN ERESOURCE_THREAD ResourceThreadId) 305 { 306 PINTERNAL_BCB iBcb = Bcb; 307 308 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId); 309 310 if (iBcb->Pinned) 311 { 312 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId); 313 iBcb->Pinned = FALSE; 314 iBcb->Vacb->PinCount--; 315 } 316 317 if (--iBcb->RefCount == 0) 318 { 319 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap, 320 iBcb->Vacb, 321 TRUE, 322 iBcb->Dirty, 323 FALSE); 324 325 ExDeleteResourceLite(&iBcb->Lock); 326 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 327 } 328 } 329 330 /* 331 * @implemented 332 */ 333 VOID 334 NTAPI 335 CcRepinBcb ( 336 IN PVOID Bcb) 337 { 338 PINTERNAL_BCB iBcb = Bcb; 339 340 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb); 341 342 iBcb->RefCount++; 343 } 344 345 /* 346 * @unimplemented 347 */ 348 VOID 349 NTAPI 350 CcUnpinRepinnedBcb ( 351 IN PVOID Bcb, 352 IN BOOLEAN WriteThrough, 353 IN PIO_STATUS_BLOCK IoStatus) 354 { 355 PINTERNAL_BCB iBcb = Bcb; 356 357 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough); 358 359 IoStatus->Status = STATUS_SUCCESS; 360 if (--iBcb->RefCount == 0) 361 { 362 IoStatus->Information = 0; 363 if (WriteThrough) 364 { 365 if (iBcb->Vacb->Dirty) 366 { 367 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb); 368 } 369 else 370 { 371 IoStatus->Status = STATUS_SUCCESS; 372 } 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 iBcb->Vacb->PinCount--; 384 ASSERT(iBcb->Vacb->PinCount == 0); 385 } 386 387 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap, 388 iBcb->Vacb, 389 TRUE, 390 iBcb->Dirty, 391 FALSE); 392 393 ExDeleteResourceLite(&iBcb->Lock); 394 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 395 } 396 } 397