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