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