[NTOSKRNL] Group files in the project file based on directory layout
[reactos.git] / ntoskrnl / cc / pin.c
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 }