xref: /reactos/ntoskrnl/cc/pin.c (revision c501d811)
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  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15 
16 /* GLOBALS *******************************************************************/
17 
18 extern NPAGED_LOOKASIDE_LIST iBcbLookasideList;
19 
20 /* FUNCTIONS *****************************************************************/
21 
22 /*
23  * @implemented
24  */
25 BOOLEAN STDCALL
26 CcMapData (IN PFILE_OBJECT FileObject,
27 	   IN PLARGE_INTEGER FileOffset,
28 	   IN ULONG Length,
29 	   IN ULONG Flags,
30 	   OUT PVOID *pBcb,
31 	   OUT PVOID *pBuffer)
32 {
33   ULONG ReadOffset;
34   BOOLEAN Valid;
35   PBCB Bcb;
36   PCACHE_SEGMENT CacheSeg;
37   NTSTATUS Status;
38   PINTERNAL_BCB iBcb;
39   ULONG ROffset;
40 
41   DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %d, Flags %d,"
42 	 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart,
43 	 Length, Flags, pBcb, pBuffer);
44 
45   ReadOffset = (ULONG)FileOffset->QuadPart;
46 
47   ASSERT(FileObject);
48   ASSERT(FileObject->SectionObjectPointer);
49   ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
50 
51   Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
52   ASSERT(Bcb);
53 
54   DPRINT("AllocationSize %I64x, FileSize %I64x\n",
55          Bcb->AllocationSize.QuadPart,
56          Bcb->FileSize.QuadPart);
57 
58   if (ReadOffset % Bcb->CacheSegmentSize + Length > Bcb->CacheSegmentSize)
59     {
60       return(FALSE);
61     }
62   ROffset = ROUND_DOWN (ReadOffset, Bcb->CacheSegmentSize);
63   Status = CcRosRequestCacheSegment(Bcb,
64 				    ROffset,
65 				    pBuffer,
66 				    &Valid,
67 				    &CacheSeg);
68   if (!NT_SUCCESS(Status))
69     {
70       return(FALSE);
71     }
72   if (!Valid)
73     {
74       if (!(Flags & MAP_WAIT))
75 	{
76           CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
77 	  return(FALSE);
78 	}
79       if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
80 	{
81           CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
82 	  return(FALSE);
83 	}
84     }
85 
86   *pBuffer = (PVOID)((ULONG_PTR)(*pBuffer) + (ReadOffset % Bcb->CacheSegmentSize));
87   iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
88   if (iBcb == NULL)
89     {
90       CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
91       return FALSE;
92     }
93   memset(iBcb, 0, sizeof(INTERNAL_BCB));
94   iBcb->PFCB.NodeTypeCode = 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */
95   iBcb->PFCB.NodeByteSize = sizeof(PUBLIC_BCB);
96   iBcb->PFCB.MappedLength = Length;
97   iBcb->PFCB.MappedFileOffset = *FileOffset;
98   iBcb->CacheSegment = CacheSeg;
99   iBcb->Dirty = FALSE;
100   iBcb->RefCount = 1;
101   *pBcb = (PVOID)iBcb;
102   return(TRUE);
103 }
104 
105 /*
106  * @unimplemented
107  */
108 BOOLEAN
109 STDCALL
110 CcPinMappedData (
111 	IN	PFILE_OBJECT		FileObject,
112 	IN	PLARGE_INTEGER		FileOffset,
113 	IN	ULONG			Length,
114 	IN	ULONG			Flags,
115 	OUT	PVOID			* Bcb
116 	)
117 {
118   /* no-op for current implementation. */
119   return TRUE;
120 }
121 
122 /*
123  * @unimplemented
124  */
125 BOOLEAN
126 STDCALL
127 CcPinRead (
128 	IN	PFILE_OBJECT		FileObject,
129 	IN	PLARGE_INTEGER		FileOffset,
130 	IN	ULONG			Length,
131 	IN	ULONG			Flags,
132 	OUT	PVOID			* Bcb,
133 	OUT	PVOID			* Buffer
134 	)
135 {
136   if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
137   {
138     if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
139       return TRUE;
140     else
141       CcUnpinData(Bcb);
142   }
143   return FALSE;
144 }
145 
146 /*
147  * @unimplemented
148  */
149 BOOLEAN
150 STDCALL
151 CcPreparePinWrite (
152 	IN	PFILE_OBJECT		FileObject,
153 	IN	PLARGE_INTEGER		FileOffset,
154 	IN	ULONG			Length,
155 	IN	BOOLEAN			Zero,
156 	IN	ULONG			Flags,
157 	OUT	PVOID			* Bcb,
158 	OUT	PVOID			* Buffer
159 	)
160 {
161         /*
162          * FIXME: This is function is similar to CcPinRead, but doesn't
163          * read the data if they're not present. Instead it should just
164          * prepare the cache segments and zero them out if Zero == TRUE.
165          *
166          * For now calling CcPinRead is better than returning error or
167          * just having UNIMPLEMENTED here.
168          */
169         return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
170 }
171 
172 /*
173  * @implemented
174  */
175 VOID STDCALL
176 CcSetDirtyPinnedData (IN PVOID Bcb,
177 		      IN PLARGE_INTEGER Lsn)
178 {
179    PINTERNAL_BCB iBcb = Bcb;
180    iBcb->Dirty = TRUE;
181 }
182 
183 
184 /*
185  * @implemented
186  */
187 VOID STDCALL
188 CcUnpinData (IN PVOID Bcb)
189 {
190   PINTERNAL_BCB iBcb = Bcb;
191   CcRosReleaseCacheSegment(iBcb->CacheSegment->Bcb, iBcb->CacheSegment, TRUE,
192                            iBcb->Dirty, FALSE);
193   if (--iBcb->RefCount == 0)
194   {
195     ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
196   }
197 }
198 
199 /*
200  * @unimplemented
201  */
202 VOID
203 STDCALL
204 CcUnpinDataForThread (
205 	IN	PVOID			Bcb,
206 	IN	ERESOURCE_THREAD	ResourceThreadId
207 	)
208 {
209 	UNIMPLEMENTED;
210 }
211 
212 /*
213  * @implemented
214  */
215 VOID
216 STDCALL
217 CcRepinBcb (
218 	IN	PVOID	Bcb
219 	)
220 {
221   PINTERNAL_BCB iBcb = Bcb;
222   iBcb->RefCount++;
223 }
224 
225 /*
226  * @unimplemented
227  */
228 VOID
229 STDCALL
230 CcUnpinRepinnedBcb (
231 	IN	PVOID			Bcb,
232 	IN	BOOLEAN			WriteThrough,
233 	IN	PIO_STATUS_BLOCK	IoStatus
234 	)
235 {
236   PINTERNAL_BCB iBcb = Bcb;
237 
238   if (--iBcb->RefCount == 0)
239     {
240       IoStatus->Information = 0;
241       if (WriteThrough)
242         {
243           ExAcquirePushLockExclusive(&iBcb->CacheSegment->Lock);
244           if (iBcb->CacheSegment->Dirty)
245             {
246               IoStatus->Status = CcRosFlushCacheSegment(iBcb->CacheSegment);
247             }
248           else
249             {
250               IoStatus->Status = STATUS_SUCCESS;
251             }
252           ExReleasePushLockExclusive(&iBcb->CacheSegment->Lock);
253         }
254       else
255         {
256           IoStatus->Status = STATUS_SUCCESS;
257         }
258 
259       ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
260     }
261 }
262