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 * - Number of calls to CcPinMappedDataCount 27 */ 28 ULONG CcMapDataWait = 0; 29 ULONG CcMapDataNoWait = 0; 30 ULONG CcPinReadWait = 0; 31 ULONG CcPinReadNoWait = 0; 32 ULONG CcPinMappedDataCount = 0; 33 34 /* FUNCTIONS *****************************************************************/ 35 36 static 37 PINTERNAL_BCB 38 NTAPI 39 CcpFindBcb( 40 IN PROS_SHARED_CACHE_MAP SharedCacheMap, 41 IN PLARGE_INTEGER FileOffset, 42 IN ULONG Length, 43 IN BOOLEAN Pinned) 44 { 45 PINTERNAL_BCB Bcb; 46 BOOLEAN Found = FALSE; 47 PLIST_ENTRY NextEntry; 48 49 for (NextEntry = SharedCacheMap->BcbList.Flink; 50 NextEntry != &SharedCacheMap->BcbList; 51 NextEntry = NextEntry->Flink) 52 { 53 Bcb = CONTAINING_RECORD(NextEntry, INTERNAL_BCB, BcbEntry); 54 55 if (Bcb->PFCB.MappedFileOffset.QuadPart <= FileOffset->QuadPart && 56 (Bcb->PFCB.MappedFileOffset.QuadPart + Bcb->PFCB.MappedLength) >= 57 (FileOffset->QuadPart + Length)) 58 { 59 if ((Pinned && Bcb->PinCount > 0) || (!Pinned && Bcb->PinCount == 0)) 60 { 61 Found = TRUE; 62 break; 63 } 64 } 65 } 66 67 return (Found ? Bcb : NULL); 68 } 69 70 static 71 VOID 72 CcpDereferenceBcb( 73 IN PROS_SHARED_CACHE_MAP SharedCacheMap, 74 IN PINTERNAL_BCB Bcb) 75 { 76 ULONG RefCount; 77 KIRQL OldIrql; 78 79 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql); 80 RefCount = --Bcb->RefCount; 81 if (RefCount == 0) 82 { 83 RemoveEntryList(&Bcb->BcbEntry); 84 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 85 86 ASSERT(Bcb->PinCount == 0); 87 /* 88 * Don't mark dirty, if it was dirty, 89 * the VACB was already marked as such 90 * following the call to CcSetDirtyPinnedData 91 */ 92 CcRosReleaseVacb(SharedCacheMap, 93 Bcb->Vacb, 94 FALSE, 95 FALSE); 96 97 ExDeleteResourceLite(&Bcb->Lock); 98 ExFreeToNPagedLookasideList(&iBcbLookasideList, Bcb); 99 } 100 else 101 { 102 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 103 } 104 } 105 106 static 107 PVOID 108 CcpGetAppropriateBcb( 109 IN PROS_SHARED_CACHE_MAP SharedCacheMap, 110 IN PROS_VACB Vacb, 111 IN PLARGE_INTEGER FileOffset, 112 IN ULONG Length, 113 IN ULONG PinFlags, 114 IN BOOLEAN ToPin) 115 { 116 KIRQL OldIrql; 117 BOOLEAN Result; 118 PINTERNAL_BCB iBcb, DupBcb; 119 120 iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList); 121 if (iBcb == NULL) 122 { 123 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE); 124 return NULL; 125 } 126 127 RtlZeroMemory(iBcb, sizeof(*iBcb)); 128 iBcb->PFCB.NodeTypeCode = 0x2FD; /* As per KMTests */ 129 iBcb->PFCB.NodeByteSize = 0; 130 iBcb->PFCB.MappedLength = Length; 131 iBcb->PFCB.MappedFileOffset = *FileOffset; 132 iBcb->Vacb = Vacb; 133 iBcb->PinCount = 0; 134 iBcb->RefCount = 1; 135 ExInitializeResourceLite(&iBcb->Lock); 136 137 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql); 138 139 /* Check if we raced with another BCB creation */ 140 DupBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, ToPin); 141 /* Yes, and we've lost */ 142 if (DupBcb != NULL) 143 { 144 /* We will return that BCB */ 145 ++DupBcb->RefCount; 146 Result = TRUE; 147 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 148 149 if (ToPin) 150 { 151 if (BooleanFlagOn(PinFlags, PIN_EXCLUSIVE)) 152 { 153 Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT)); 154 } 155 else 156 { 157 Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT)); 158 } 159 160 if (Result) 161 { 162 DupBcb->PinCount++; 163 } 164 else 165 { 166 CcpDereferenceBcb(SharedCacheMap, DupBcb); 167 DupBcb = NULL; 168 } 169 } 170 171 if (DupBcb != NULL) 172 { 173 /* Delete the loser */ 174 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE); 175 ExDeleteResourceLite(&iBcb->Lock); 176 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 177 } 178 179 /* Return the winner - no need to update buffer address, it's 180 * relative to the VACB, which is unchanged. 181 */ 182 iBcb = DupBcb; 183 } 184 /* Nope, insert ourselves */ 185 else 186 { 187 if (ToPin) 188 { 189 iBcb->PinCount++; 190 191 if (BooleanFlagOn(PinFlags, PIN_EXCLUSIVE)) 192 { 193 Result = ExAcquireResourceExclusiveLite(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT)); 194 } 195 else 196 { 197 Result = ExAcquireSharedStarveExclusive(&iBcb->Lock, BooleanFlagOn(PinFlags, PIN_WAIT)); 198 } 199 200 ASSERT(Result); 201 } 202 203 InsertTailList(&SharedCacheMap->BcbList, &iBcb->BcbEntry); 204 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 205 } 206 207 return iBcb; 208 } 209 210 static 211 BOOLEAN 212 CcpPinData( 213 IN PROS_SHARED_CACHE_MAP SharedCacheMap, 214 IN PLARGE_INTEGER FileOffset, 215 IN ULONG Length, 216 IN ULONG Flags, 217 OUT PVOID * Bcb, 218 OUT PVOID * Buffer) 219 { 220 PINTERNAL_BCB NewBcb; 221 KIRQL OldIrql; 222 ULONG VacbOffset; 223 NTSTATUS Status; 224 _SEH2_VOLATILE BOOLEAN Result; 225 226 VacbOffset = (ULONG)(FileOffset->QuadPart % VACB_MAPPING_GRANULARITY); 227 228 if ((VacbOffset + Length) > VACB_MAPPING_GRANULARITY) 229 { 230 /* Complain loudly, we shoud pin the whole range */ 231 DPRINT1("TRUNCATING DATA PIN FROM %lu to %lu!\n", Length, VACB_MAPPING_GRANULARITY - VacbOffset); 232 Length = VACB_MAPPING_GRANULARITY - VacbOffset; 233 } 234 235 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql); 236 NewBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, TRUE); 237 238 if (NewBcb != NULL) 239 { 240 BOOLEAN Result; 241 242 ++NewBcb->RefCount; 243 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 244 245 if (BooleanFlagOn(Flags, PIN_EXCLUSIVE)) 246 Result = ExAcquireResourceExclusiveLite(&NewBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT)); 247 else 248 Result = ExAcquireSharedStarveExclusive(&NewBcb->Lock, BooleanFlagOn(Flags, PIN_WAIT)); 249 250 if (!Result) 251 { 252 CcpDereferenceBcb(SharedCacheMap, NewBcb); 253 return FALSE; 254 } 255 256 NewBcb->PinCount++; 257 } 258 else 259 { 260 LONGLONG ROffset; 261 PROS_VACB Vacb; 262 263 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 264 265 if (BooleanFlagOn(Flags, PIN_IF_BCB)) 266 { 267 return FALSE; 268 } 269 270 /* Properly round offset and call internal helper for getting a VACB */ 271 ROffset = ROUND_DOWN(FileOffset->QuadPart, VACB_MAPPING_GRANULARITY); 272 Status = CcRosGetVacb(SharedCacheMap, ROffset, &Vacb); 273 if (!NT_SUCCESS(Status)) 274 { 275 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 276 SharedCacheMap->FileObject, FileOffset, Length, Flags); 277 ExRaiseStatus(Status); 278 return FALSE; 279 } 280 281 NewBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, Flags, TRUE); 282 if (NewBcb == NULL) 283 { 284 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE); 285 return FALSE; 286 } 287 } 288 289 Result = FALSE; 290 _SEH2_TRY 291 { 292 /* Ensure the pages are resident */ 293 Result = CcRosEnsureVacbResident(NewBcb->Vacb, 294 BooleanFlagOn(Flags, PIN_WAIT), 295 BooleanFlagOn(Flags, PIN_NO_READ), 296 VacbOffset, Length); 297 } 298 _SEH2_FINALLY 299 { 300 if (!Result) 301 { 302 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 303 SharedCacheMap->FileObject, FileOffset, Length, Flags); 304 CcUnpinData(&NewBcb->PFCB); 305 *Bcb = NULL; 306 *Buffer = NULL; 307 } 308 } 309 _SEH2_END; 310 311 if (Result) 312 { 313 *Bcb = &NewBcb->PFCB; 314 *Buffer = (PVOID)((ULONG_PTR)NewBcb->Vacb->BaseAddress + VacbOffset); 315 } 316 317 return Result; 318 } 319 320 /* 321 * @implemented 322 */ 323 BOOLEAN 324 NTAPI 325 CcMapData ( 326 IN PFILE_OBJECT FileObject, 327 IN PLARGE_INTEGER FileOffset, 328 IN ULONG Length, 329 IN ULONG Flags, 330 OUT PVOID *pBcb, 331 OUT PVOID *pBuffer) 332 { 333 KIRQL OldIrql; 334 PINTERNAL_BCB iBcb; 335 PROS_VACB Vacb; 336 PROS_SHARED_CACHE_MAP SharedCacheMap; 337 ULONG VacbOffset; 338 NTSTATUS Status; 339 _SEH2_VOLATILE BOOLEAN Result; 340 341 CCTRACE(CC_API_DEBUG, "CcMapData(FileObject 0x%p, FileOffset 0x%I64x, Length %lu, Flags 0x%lx," 342 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart, 343 Length, Flags, pBcb, pBuffer); 344 345 ASSERT(FileObject); 346 ASSERT(FileObject->SectionObjectPointer); 347 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap); 348 349 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 350 ASSERT(SharedCacheMap); 351 352 if (Flags & MAP_WAIT) 353 { 354 ++CcMapDataWait; 355 } 356 else 357 { 358 ++CcMapDataNoWait; 359 } 360 361 VacbOffset = (ULONG)(FileOffset->QuadPart % VACB_MAPPING_GRANULARITY); 362 /* KMTests seem to show that it is allowed to call accross mapping granularity */ 363 if ((VacbOffset + Length) > VACB_MAPPING_GRANULARITY) 364 { 365 DPRINT1("TRUNCATING DATA MAP FROM %lu to %lu!\n", Length, VACB_MAPPING_GRANULARITY - VacbOffset); 366 Length = VACB_MAPPING_GRANULARITY - VacbOffset; 367 } 368 369 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql); 370 iBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, FALSE); 371 372 if (iBcb == NULL) 373 { 374 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 375 376 /* Call internal helper for getting a VACB */ 377 Status = CcRosGetVacb(SharedCacheMap, FileOffset->QuadPart, &Vacb); 378 if (!NT_SUCCESS(Status)) 379 { 380 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 381 SharedCacheMap->FileObject, FileOffset, Length, Flags); 382 ExRaiseStatus(Status); 383 } 384 385 iBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, 0, FALSE); 386 if (iBcb == NULL) 387 { 388 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE); 389 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n", 390 SharedCacheMap->FileObject, FileOffset, Length, Flags); 391 *pBcb = NULL; // If you ever remove this for compat, make sure to review all callers for using an unititialized value 392 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 393 } 394 } 395 else 396 { 397 ++iBcb->RefCount; 398 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 399 } 400 401 _SEH2_TRY 402 { 403 Result = FALSE; 404 /* Ensure the pages are resident */ 405 Result = CcRosEnsureVacbResident(iBcb->Vacb, BooleanFlagOn(Flags, MAP_WAIT), 406 BooleanFlagOn(Flags, MAP_NO_READ), VacbOffset, Length); 407 } 408 _SEH2_FINALLY 409 { 410 if (!Result) 411 { 412 CcpDereferenceBcb(SharedCacheMap, iBcb); 413 *pBcb = NULL; 414 *pBuffer = NULL; 415 } 416 } 417 _SEH2_END; 418 419 if (Result) 420 { 421 *pBcb = &iBcb->PFCB; 422 *pBuffer = (PVOID)((ULONG_PTR)iBcb->Vacb->BaseAddress + VacbOffset); 423 } 424 425 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p, Buffer %p\n", 426 FileObject, FileOffset, Length, Flags, *pBcb, *pBuffer); 427 return Result; 428 } 429 430 /* 431 * @unimplemented 432 */ 433 BOOLEAN 434 NTAPI 435 CcPinMappedData ( 436 IN PFILE_OBJECT FileObject, 437 IN PLARGE_INTEGER FileOffset, 438 IN ULONG Length, 439 IN ULONG Flags, 440 OUT PVOID * Bcb) 441 { 442 BOOLEAN Result; 443 PVOID Buffer; 444 PINTERNAL_BCB iBcb; 445 PROS_SHARED_CACHE_MAP SharedCacheMap; 446 447 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx\n", 448 FileObject, FileOffset, Length, Flags); 449 450 ASSERT(FileObject); 451 ASSERT(FileObject->SectionObjectPointer); 452 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap); 453 454 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 455 ASSERT(SharedCacheMap); 456 if (!SharedCacheMap->PinAccess) 457 { 458 DPRINT1("FIXME: Pinning a file with no pin access!\n"); 459 return FALSE; 460 } 461 462 iBcb = *Bcb ? CONTAINING_RECORD(*Bcb, INTERNAL_BCB, PFCB) : NULL; 463 464 ++CcPinMappedDataCount; 465 466 Result = CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, &Buffer); 467 if (Result) 468 { 469 CcUnpinData(&iBcb->PFCB); 470 } 471 472 return Result; 473 } 474 475 /* 476 * @unimplemented 477 */ 478 BOOLEAN 479 NTAPI 480 CcPinRead ( 481 IN PFILE_OBJECT FileObject, 482 IN PLARGE_INTEGER FileOffset, 483 IN ULONG Length, 484 IN ULONG Flags, 485 OUT PVOID * Bcb, 486 OUT PVOID * Buffer) 487 { 488 PROS_SHARED_CACHE_MAP SharedCacheMap; 489 490 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n", 491 FileObject, FileOffset, Length, Flags); 492 493 ASSERT(FileObject); 494 ASSERT(FileObject->SectionObjectPointer); 495 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap); 496 497 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 498 ASSERT(SharedCacheMap); 499 if (!SharedCacheMap->PinAccess) 500 { 501 DPRINT1("FIXME: Pinning a file with no pin access!\n"); 502 return FALSE; 503 } 504 505 if (Flags & PIN_WAIT) 506 { 507 ++CcPinReadWait; 508 } 509 else 510 { 511 ++CcPinReadNoWait; 512 } 513 514 return CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, Buffer); 515 } 516 517 /* 518 * @unimplemented 519 */ 520 BOOLEAN 521 NTAPI 522 CcPreparePinWrite ( 523 IN PFILE_OBJECT FileObject, 524 IN PLARGE_INTEGER FileOffset, 525 IN ULONG Length, 526 IN BOOLEAN Zero, 527 IN ULONG Flags, 528 OUT PVOID * Bcb, 529 OUT PVOID * Buffer) 530 { 531 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n", 532 FileObject, FileOffset, Length, Zero, Flags); 533 534 /* 535 * FIXME: This is function is similar to CcPinRead, but doesn't 536 * read the data if they're not present. Instead it should just 537 * prepare the VACBs and zero them out if Zero != FALSE. 538 * 539 * For now calling CcPinRead is better than returning error or 540 * just having UNIMPLEMENTED here. 541 */ 542 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer); 543 } 544 545 /* 546 * @implemented 547 */ 548 VOID NTAPI 549 CcSetDirtyPinnedData ( 550 IN PVOID Bcb, 551 IN PLARGE_INTEGER Lsn) 552 { 553 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB); 554 555 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", Bcb, Lsn); 556 557 /* Tell Mm */ 558 MmMakePagesDirty(NULL, 559 Add2Ptr(iBcb->Vacb->BaseAddress, iBcb->PFCB.MappedFileOffset.QuadPart - iBcb->Vacb->FileOffset.QuadPart), 560 iBcb->PFCB.MappedLength); 561 562 if (!iBcb->Vacb->Dirty) 563 { 564 CcRosMarkDirtyVacb(iBcb->Vacb); 565 } 566 } 567 568 569 /* 570 * @implemented 571 */ 572 VOID NTAPI 573 CcUnpinData ( 574 IN PVOID Bcb) 575 { 576 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb); 577 578 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread()); 579 } 580 581 /* 582 * @unimplemented 583 */ 584 VOID 585 NTAPI 586 CcUnpinDataForThread ( 587 IN PVOID Bcb, 588 IN ERESOURCE_THREAD ResourceThreadId) 589 { 590 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB); 591 592 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId); 593 594 if (iBcb->PinCount != 0) 595 { 596 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId); 597 iBcb->PinCount--; 598 } 599 600 CcpDereferenceBcb(iBcb->Vacb->SharedCacheMap, iBcb); 601 } 602 603 /* 604 * @implemented 605 */ 606 VOID 607 NTAPI 608 CcRepinBcb ( 609 IN PVOID Bcb) 610 { 611 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB); 612 613 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb); 614 615 iBcb->RefCount++; 616 } 617 618 /* 619 * @unimplemented 620 */ 621 VOID 622 NTAPI 623 CcUnpinRepinnedBcb ( 624 IN PVOID Bcb, 625 IN BOOLEAN WriteThrough, 626 IN PIO_STATUS_BLOCK IoStatus) 627 { 628 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB); 629 KIRQL OldIrql; 630 PROS_SHARED_CACHE_MAP SharedCacheMap; 631 632 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough); 633 634 SharedCacheMap = iBcb->Vacb->SharedCacheMap; 635 IoStatus->Status = STATUS_SUCCESS; 636 637 if (WriteThrough) 638 { 639 CcFlushCache(iBcb->Vacb->SharedCacheMap->FileObject->SectionObjectPointer, 640 &iBcb->PFCB.MappedFileOffset, 641 iBcb->PFCB.MappedLength, 642 IoStatus); 643 } 644 else 645 { 646 IoStatus->Status = STATUS_SUCCESS; 647 IoStatus->Information = 0; 648 } 649 650 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql); 651 if (--iBcb->RefCount == 0) 652 { 653 RemoveEntryList(&iBcb->BcbEntry); 654 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 655 656 if (iBcb->PinCount != 0) 657 { 658 ExReleaseResourceLite(&iBcb->Lock); 659 iBcb->PinCount--; 660 ASSERT(iBcb->PinCount == 0); 661 } 662 663 /* 664 * Don't mark dirty, if it was dirty, 665 * the VACB was already marked as such 666 * following the call to CcSetDirtyPinnedData 667 */ 668 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap, 669 iBcb->Vacb, 670 FALSE, 671 FALSE); 672 673 ExDeleteResourceLite(&iBcb->Lock); 674 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 675 } 676 else 677 { 678 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); 679 } 680 } 681