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