7b8d8787310e205c681a57932d799c5ffa295d88
[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 /* FUNCTIONS *****************************************************************/
22
23 /*
24 * @implemented
25 */
26 BOOLEAN
27 NTAPI
28 CcMapData (
29 IN PFILE_OBJECT FileObject,
30 IN PLARGE_INTEGER FileOffset,
31 IN ULONG Length,
32 IN ULONG Flags,
33 OUT PVOID *pBcb,
34 OUT PVOID *pBuffer)
35 {
36 LONGLONG ReadOffset;
37 BOOLEAN Valid;
38 PROS_SHARED_CACHE_MAP SharedCacheMap;
39 PROS_VACB Vacb;
40 NTSTATUS Status;
41 PINTERNAL_BCB iBcb;
42 LONGLONG ROffset;
43
44 DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %lu, Flags 0x%lx,"
45 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart,
46 Length, Flags, pBcb, pBuffer);
47
48 ReadOffset = FileOffset->QuadPart;
49
50 ASSERT(FileObject);
51 ASSERT(FileObject->SectionObjectPointer);
52 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
53
54 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
55 ASSERT(SharedCacheMap);
56
57 DPRINT("SectionSize %I64x, FileSize %I64x\n",
58 SharedCacheMap->SectionSize.QuadPart,
59 SharedCacheMap->FileSize.QuadPart);
60
61 if (ReadOffset % VACB_MAPPING_GRANULARITY + Length > VACB_MAPPING_GRANULARITY)
62 {
63 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
64 FileObject, FileOffset, Length, Flags);
65 ExRaiseStatus(STATUS_INVALID_PARAMETER);
66 return FALSE;
67 }
68
69 ROffset = ROUND_DOWN(ReadOffset, VACB_MAPPING_GRANULARITY);
70 Status = CcRosRequestVacb(SharedCacheMap,
71 ROffset,
72 pBuffer,
73 &Valid,
74 &Vacb);
75 if (!NT_SUCCESS(Status))
76 {
77 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
78 FileObject, FileOffset, Length, Flags);
79 ExRaiseStatus(Status);
80 return FALSE;
81 }
82
83 if (!Valid)
84 {
85 if (!(Flags & MAP_WAIT))
86 {
87 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
88 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
89 FileObject, FileOffset, Length, Flags);
90 return FALSE;
91 }
92
93 Status = CcReadVirtualAddress(Vacb);
94 if (!NT_SUCCESS(Status))
95 {
96 CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
97 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
98 FileObject, FileOffset, Length, Flags);
99 ExRaiseStatus(Status);
100 return FALSE;
101 }
102 }
103
104 *pBuffer = (PUCHAR)*pBuffer + ReadOffset % VACB_MAPPING_GRANULARITY;
105 iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
106 if (iBcb == NULL)
107 {
108 CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
109 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> FALSE\n",
110 FileObject, FileOffset, Length, Flags);
111 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
112 return FALSE;
113 }
114
115 RtlZeroMemory(iBcb, sizeof(*iBcb));
116 iBcb->PFCB.NodeTypeCode = 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */
117 iBcb->PFCB.NodeByteSize = sizeof(PUBLIC_BCB);
118 iBcb->PFCB.MappedLength = Length;
119 iBcb->PFCB.MappedFileOffset = *FileOffset;
120 iBcb->Vacb = Vacb;
121 iBcb->Dirty = FALSE;
122 iBcb->Pinned = FALSE;
123 iBcb->RefCount = 1;
124 ExInitializeResourceLite(&iBcb->Lock);
125 *pBcb = (PVOID)iBcb;
126
127 CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p\n",
128 FileObject, FileOffset, Length, Flags, iBcb);
129 return TRUE;
130 }
131
132 /*
133 * @unimplemented
134 */
135 BOOLEAN
136 NTAPI
137 CcPinMappedData (
138 IN PFILE_OBJECT FileObject,
139 IN PLARGE_INTEGER FileOffset,
140 IN ULONG Length,
141 IN ULONG Flags,
142 OUT PVOID * Bcb)
143 {
144 PROS_SHARED_CACHE_MAP SharedCacheMap;
145
146 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
147 FileObject, FileOffset, Length, Flags);
148
149 ASSERT(FileObject);
150 ASSERT(FileObject->SectionObjectPointer);
151 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap);
152
153 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
154 ASSERT(SharedCacheMap);
155 ASSERT(SharedCacheMap->PinAccess);
156
157 /* no-op for current implementation. */
158 return TRUE;
159 }
160
161 /*
162 * @unimplemented
163 */
164 BOOLEAN
165 NTAPI
166 CcPinRead (
167 IN PFILE_OBJECT FileObject,
168 IN PLARGE_INTEGER FileOffset,
169 IN ULONG Length,
170 IN ULONG Flags,
171 OUT PVOID * Bcb,
172 OUT PVOID * Buffer)
173 {
174 PINTERNAL_BCB iBcb;
175
176 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
177 FileObject, FileOffset, Length, Flags);
178
179 if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
180 {
181 if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
182 {
183 iBcb = *Bcb;
184
185 ASSERT(iBcb->Pinned == FALSE);
186
187 iBcb->Pinned = TRUE;
188 iBcb->Vacb->PinCount++;
189 CcRosReleaseVacbLock(iBcb->Vacb);
190
191 if (Flags & PIN_EXCLUSIVE)
192 {
193 ExAcquireResourceExclusiveLite(&iBcb->Lock, TRUE);
194 }
195 else
196 {
197 ExAcquireResourceSharedLite(&iBcb->Lock, TRUE);
198 }
199
200 return TRUE;
201 }
202 else
203 CcUnpinData(*Bcb);
204 }
205 return FALSE;
206 }
207
208 /*
209 * @unimplemented
210 */
211 BOOLEAN
212 NTAPI
213 CcPreparePinWrite (
214 IN PFILE_OBJECT FileObject,
215 IN PLARGE_INTEGER FileOffset,
216 IN ULONG Length,
217 IN BOOLEAN Zero,
218 IN ULONG Flags,
219 OUT PVOID * Bcb,
220 OUT PVOID * Buffer)
221 {
222 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
223 FileObject, FileOffset, Length, Zero, Flags);
224
225 /*
226 * FIXME: This is function is similar to CcPinRead, but doesn't
227 * read the data if they're not present. Instead it should just
228 * prepare the VACBs and zero them out if Zero != FALSE.
229 *
230 * For now calling CcPinRead is better than returning error or
231 * just having UNIMPLEMENTED here.
232 */
233 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
234 }
235
236 /*
237 * @implemented
238 */
239 VOID NTAPI
240 CcSetDirtyPinnedData (
241 IN PVOID Bcb,
242 IN PLARGE_INTEGER Lsn)
243 {
244 PINTERNAL_BCB iBcb = Bcb;
245
246 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n",
247 Bcb, Lsn);
248
249 iBcb->Dirty = TRUE;
250 }
251
252
253 /*
254 * @implemented
255 */
256 VOID NTAPI
257 CcUnpinData (
258 IN PVOID Bcb)
259 {
260 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
261
262 CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread());
263 }
264
265 /*
266 * @unimplemented
267 */
268 VOID
269 NTAPI
270 CcUnpinDataForThread (
271 IN PVOID Bcb,
272 IN ERESOURCE_THREAD ResourceThreadId)
273 {
274 PINTERNAL_BCB iBcb = Bcb;
275
276 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
277
278 if (iBcb->Pinned)
279 {
280 ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId);
281 iBcb->Pinned = FALSE;
282 CcRosAcquireVacbLock(iBcb->Vacb, NULL);
283 iBcb->Vacb->PinCount--;
284 }
285
286 if (--iBcb->RefCount == 0)
287 {
288 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
289 iBcb->Vacb,
290 TRUE,
291 iBcb->Dirty,
292 FALSE);
293
294 ExDeleteResourceLite(&iBcb->Lock);
295 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
296 }
297 }
298
299 /*
300 * @implemented
301 */
302 VOID
303 NTAPI
304 CcRepinBcb (
305 IN PVOID Bcb)
306 {
307 PINTERNAL_BCB iBcb = Bcb;
308
309 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
310
311 iBcb->RefCount++;
312 }
313
314 /*
315 * @unimplemented
316 */
317 VOID
318 NTAPI
319 CcUnpinRepinnedBcb (
320 IN PVOID Bcb,
321 IN BOOLEAN WriteThrough,
322 IN PIO_STATUS_BLOCK IoStatus)
323 {
324 PINTERNAL_BCB iBcb = Bcb;
325
326 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
327
328 IoStatus->Status = STATUS_SUCCESS;
329 if (--iBcb->RefCount == 0)
330 {
331 IoStatus->Information = 0;
332 if (WriteThrough)
333 {
334 CcRosAcquireVacbLock(iBcb->Vacb, NULL);
335 if (iBcb->Vacb->Dirty)
336 {
337 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
338 }
339 else
340 {
341 IoStatus->Status = STATUS_SUCCESS;
342 }
343 CcRosReleaseVacbLock(iBcb->Vacb);
344 }
345 else
346 {
347 IoStatus->Status = STATUS_SUCCESS;
348 }
349
350 if (iBcb->Pinned)
351 {
352 ExReleaseResourceLite(&iBcb->Lock);
353 iBcb->Pinned = FALSE;
354 CcRosAcquireVacbLock(iBcb->Vacb, NULL);
355 iBcb->Vacb->PinCount--;
356 }
357 ExDeleteResourceLite(&iBcb->Lock);
358 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
359 }
360 }