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
CcpFindBcb(IN PROS_SHARED_CACHE_MAP SharedCacheMap,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Pinned)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
CcpDereferenceBcb(IN PROS_SHARED_CACHE_MAP SharedCacheMap,IN PINTERNAL_BCB Bcb)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
CcpGetAppropriateBcb(IN PROS_SHARED_CACHE_MAP SharedCacheMap,IN PROS_VACB Vacb,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG PinFlags,IN BOOLEAN ToPin)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
CcpPinData(IN PROS_SHARED_CACHE_MAP SharedCacheMap,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID * Bcb,OUT PVOID * Buffer)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
CcMapData(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID * pBcb,OUT PVOID * pBuffer)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
CcPinMappedData(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID * Bcb)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
CcPinRead(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID * Bcb,OUT PVOID * Buffer)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
CcPreparePinWrite(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Zero,IN ULONG Flags,OUT PVOID * Bcb,OUT PVOID * Buffer)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
CcSetDirtyPinnedData(IN PVOID Bcb,IN PLARGE_INTEGER Lsn)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
CcUnpinData(IN PVOID Bcb)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
CcUnpinDataForThread(IN PVOID Bcb,IN ERESOURCE_THREAD ResourceThreadId)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
CcRepinBcb(IN PVOID Bcb)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
CcUnpinRepinnedBcb(IN PVOID Bcb,IN BOOLEAN WriteThrough,IN PIO_STATUS_BLOCK IoStatus)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