[MSGINA][SHELL32] Rework friendly UI shutdown dialog box and implement friendly UI...
[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 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 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 return FALSE;
306 }
307 }
308 _SEH2_END;
309
310 *Bcb = &NewBcb->PFCB;
311 *Buffer = (PVOID)((ULONG_PTR)NewBcb->Vacb->BaseAddress + VacbOffset);
312
313 return TRUE;
314 }
315
316 /*
317 * @implemented
318 */
319 BOOLEAN
320 NTAPI
321 CcMapData (
322 IN PFILE_OBJECT FileObject,
323 IN PLARGE_INTEGER FileOffset,
324 IN ULONG Length,
325 IN ULONG Flags,
326 OUT PVOID *pBcb,
327 OUT PVOID *pBuffer)
328 {
329 KIRQL OldIrql;
330 PINTERNAL_BCB iBcb;
331 PROS_VACB Vacb;
332 PROS_SHARED_CACHE_MAP SharedCacheMap;
333 ULONG VacbOffset;
334 NTSTATUS Status;
335 BOOLEAN Result;
336
337 CCTRACE(CC_API_DEBUG, "CcMapData(FileObject 0x%p, FileOffset 0x%I64x, Length %lu, Flags 0x%lx,"
338 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart,
339 Length, Flags, pBcb, pBuffer);
340
341 ASSERT(FileObject);
342 ASSERT(FileObject->SectionObjectPointer);
343 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
344
345 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
346 ASSERT(SharedCacheMap);
347
348 if (Flags & MAP_WAIT)
349 {
350 ++CcMapDataWait;
351 }
352 else
353 {
354 ++CcMapDataNoWait;
355 }
356
357 VacbOffset = (ULONG)(FileOffset->QuadPart % VACB_MAPPING_GRANULARITY);
358 /* KMTests seem to show that it is allowed to call accross mapping granularity */
359 if ((VacbOffset + Length) > VACB_MAPPING_GRANULARITY)
360 {
361 DPRINT1("TRUNCATING DATA MAP FROM %lu to %lu!\n", Length, VACB_MAPPING_GRANULARITY - VacbOffset);
362 Length = VACB_MAPPING_GRANULARITY - VacbOffset;
363 }
364
365 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
366 iBcb = CcpFindBcb(SharedCacheMap, FileOffset, Length, FALSE);
367
368 if (iBcb == NULL)
369 {
370 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
371
372 /* Call internal helper for getting a VACB */
373 Status = CcRosGetVacb(SharedCacheMap, FileOffset->QuadPart, &Vacb);
374 if (!NT_SUCCESS(Status))
375 {
376 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
377 SharedCacheMap->FileObject, FileOffset, Length, Flags);
378 ExRaiseStatus(Status);
379 }
380
381 iBcb = CcpGetAppropriateBcb(SharedCacheMap, Vacb, FileOffset, Length, 0, FALSE);
382 if (iBcb == NULL)
383 {
384 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE);
385 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
386 SharedCacheMap->FileObject, FileOffset, Length, Flags);
387 *pBcb = NULL; // If you ever remove this for compat, make sure to review all callers for using an unititialized value
388 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
389 }
390 }
391 else
392 {
393 ++iBcb->RefCount;
394 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
395 }
396
397 _SEH2_TRY
398 {
399 Result = FALSE;
400 /* Ensure the pages are resident */
401 Result = CcRosEnsureVacbResident(iBcb->Vacb, BooleanFlagOn(Flags, MAP_WAIT),
402 BooleanFlagOn(Flags, MAP_NO_READ), VacbOffset, Length);
403 }
404 _SEH2_FINALLY
405 {
406 if (!Result)
407 {
408 CcpDereferenceBcb(SharedCacheMap, iBcb);
409 return FALSE;
410 }
411 }
412 _SEH2_END;
413
414 *pBcb = &iBcb->PFCB;
415 *pBuffer = (PVOID)((ULONG_PTR)iBcb->Vacb->BaseAddress + VacbOffset);
416
417 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p, Buffer %p\n",
418 FileObject, FileOffset, Length, Flags, *pBcb, *pBuffer);
419 return Result;
420 }
421
422 /*
423 * @unimplemented
424 */
425 BOOLEAN
426 NTAPI
427 CcPinMappedData (
428 IN PFILE_OBJECT FileObject,
429 IN PLARGE_INTEGER FileOffset,
430 IN ULONG Length,
431 IN ULONG Flags,
432 OUT PVOID * Bcb)
433 {
434 BOOLEAN Result;
435 PVOID Buffer;
436 PINTERNAL_BCB iBcb;
437 PROS_SHARED_CACHE_MAP SharedCacheMap;
438
439 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
440 FileObject, FileOffset, Length, Flags);
441
442 ASSERT(FileObject);
443 ASSERT(FileObject->SectionObjectPointer);
444 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
445
446 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
447 ASSERT(SharedCacheMap);
448 if (!SharedCacheMap->PinAccess)
449 {
450 DPRINT1("FIXME: Pinning a file with no pin access!\n");
451 return FALSE;
452 }
453
454 iBcb = *Bcb ? CONTAINING_RECORD(*Bcb, INTERNAL_BCB, PFCB) : NULL;
455
456 ++CcPinMappedDataCount;
457
458 Result = CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, &Buffer);
459 if (Result)
460 {
461 CcUnpinData(&iBcb->PFCB);
462 }
463
464 return Result;
465 }
466
467 /*
468 * @unimplemented
469 */
470 BOOLEAN
471 NTAPI
472 CcPinRead (
473 IN PFILE_OBJECT FileObject,
474 IN PLARGE_INTEGER FileOffset,
475 IN ULONG Length,
476 IN ULONG Flags,
477 OUT PVOID * Bcb,
478 OUT PVOID * Buffer)
479 {
480 PROS_SHARED_CACHE_MAP SharedCacheMap;
481
482 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
483 FileObject, FileOffset, Length, Flags);
484
485 ASSERT(FileObject);
486 ASSERT(FileObject->SectionObjectPointer);
487 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
488
489 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
490 ASSERT(SharedCacheMap);
491 if (!SharedCacheMap->PinAccess)
492 {
493 DPRINT1("FIXME: Pinning a file with no pin access!\n");
494 return FALSE;
495 }
496
497 if (Flags & PIN_WAIT)
498 {
499 ++CcPinReadWait;
500 }
501 else
502 {
503 ++CcPinReadNoWait;
504 }
505
506 return CcpPinData(SharedCacheMap, FileOffset, Length, Flags, Bcb, Buffer);
507 }
508
509 /*
510 * @unimplemented
511 */
512 BOOLEAN
513 NTAPI
514 CcPreparePinWrite (
515 IN PFILE_OBJECT FileObject,
516 IN PLARGE_INTEGER FileOffset,
517 IN ULONG Length,
518 IN BOOLEAN Zero,
519 IN ULONG Flags,
520 OUT PVOID * Bcb,
521 OUT PVOID * Buffer)
522 {
523 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
524 FileObject, FileOffset, Length, Zero, Flags);
525
526 /*
527 * FIXME: This is function is similar to CcPinRead, but doesn't
528 * read the data if they're not present. Instead it should just
529 * prepare the VACBs and zero them out if Zero != FALSE.
530 *
531 * For now calling CcPinRead is better than returning error or
532 * just having UNIMPLEMENTED here.
533 */
534 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
535 }
536
537 /*
538 * @implemented
539 */
540 VOID NTAPI
541 CcSetDirtyPinnedData (
542 IN PVOID Bcb,
543 IN PLARGE_INTEGER Lsn)
544 {
545 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
546
547 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n", Bcb, Lsn);
548
549 /* Tell Mm */
550 MmMakePagesDirty(NULL,
551 Add2Ptr(iBcb->Vacb->BaseAddress, iBcb->PFCB.MappedFileOffset.QuadPart - iBcb->Vacb->FileOffset.QuadPart),
552 iBcb->PFCB.MappedLength);
553
554 if (!iBcb->Vacb->Dirty)
555 {
556 CcRosMarkDirtyVacb(iBcb->Vacb);
557 }
558 }
559
560
561 /*
562 * @implemented
563 */
564 VOID NTAPI
565 CcUnpinData (
566 IN PVOID Bcb)
567 {
568 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
569
570 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread());
571 }
572
573 /*
574 * @unimplemented
575 */
576 VOID
577 NTAPI
578 CcUnpinDataForThread (
579 IN PVOID Bcb,
580 IN ERESOURCE_THREAD ResourceThreadId)
581 {
582 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
583
584 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
585
586 if (iBcb->PinCount != 0)
587 {
588 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
589 iBcb->PinCount--;
590 }
591
592 CcpDereferenceBcb(iBcb->Vacb->SharedCacheMap, iBcb);
593 }
594
595 /*
596 * @implemented
597 */
598 VOID
599 NTAPI
600 CcRepinBcb (
601 IN PVOID Bcb)
602 {
603 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
604
605 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
606
607 iBcb->RefCount++;
608 }
609
610 /*
611 * @unimplemented
612 */
613 VOID
614 NTAPI
615 CcUnpinRepinnedBcb (
616 IN PVOID Bcb,
617 IN BOOLEAN WriteThrough,
618 IN PIO_STATUS_BLOCK IoStatus)
619 {
620 PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
621 KIRQL OldIrql;
622 PROS_SHARED_CACHE_MAP SharedCacheMap;
623
624 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
625
626 SharedCacheMap = iBcb->Vacb->SharedCacheMap;
627 IoStatus->Status = STATUS_SUCCESS;
628
629 if (WriteThrough)
630 {
631 CcFlushCache(iBcb->Vacb->SharedCacheMap->FileObject->SectionObjectPointer,
632 &iBcb->PFCB.MappedFileOffset,
633 iBcb->PFCB.MappedLength,
634 IoStatus);
635 }
636 else
637 {
638 IoStatus->Status = STATUS_SUCCESS;
639 IoStatus->Information = 0;
640 }
641
642 KeAcquireSpinLock(&SharedCacheMap->BcbSpinLock, &OldIrql);
643 if (--iBcb->RefCount == 0)
644 {
645 RemoveEntryList(&iBcb->BcbEntry);
646 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
647
648 if (iBcb->PinCount != 0)
649 {
650 ExReleaseResourceLite(&iBcb->Lock);
651 iBcb->PinCount--;
652 ASSERT(iBcb->PinCount == 0);
653 }
654
655 /*
656 * Don't mark dirty, if it was dirty,
657 * the VACB was already marked as such
658 * following the call to CcSetDirtyPinnedData
659 */
660 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
661 iBcb->Vacb,
662 FALSE,
663 FALSE);
664
665 ExDeleteResourceLite(&iBcb->Lock);
666 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
667 }
668 else
669 {
670 KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
671 }
672 }