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