[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 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
137 FileObject, FileOffset, Length, Flags);
138
139 /* no-op for current implementation. */
140 return TRUE;
141 }
142
143 /*
144 * @unimplemented
145 */
146 BOOLEAN
147 NTAPI
148 CcPinRead (
149 IN PFILE_OBJECT FileObject,
150 IN PLARGE_INTEGER FileOffset,
151 IN ULONG Length,
152 IN ULONG Flags,
153 OUT PVOID * Bcb,
154 OUT PVOID * Buffer)
155 {
156 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Flags=0x%lx\n",
157 FileObject, FileOffset, Length, Flags);
158
159 if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
160 {
161 if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
162 return TRUE;
163 else
164 CcUnpinData(*Bcb);
165 }
166 return FALSE;
167 }
168
169 /*
170 * @unimplemented
171 */
172 BOOLEAN
173 NTAPI
174 CcPreparePinWrite (
175 IN PFILE_OBJECT FileObject,
176 IN PLARGE_INTEGER FileOffset,
177 IN ULONG Length,
178 IN BOOLEAN Zero,
179 IN ULONG Flags,
180 OUT PVOID * Bcb,
181 OUT PVOID * Buffer)
182 {
183 CCTRACE(CC_API_DEBUG, "FileOffset=%p FileOffset=%p Length=%lu Zero=%d Flags=0x%lx\n",
184 FileObject, FileOffset, Length, Zero, Flags);
185
186 /*
187 * FIXME: This is function is similar to CcPinRead, but doesn't
188 * read the data if they're not present. Instead it should just
189 * prepare the VACBs and zero them out if Zero != FALSE.
190 *
191 * For now calling CcPinRead is better than returning error or
192 * just having UNIMPLEMENTED here.
193 */
194 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
195 }
196
197 /*
198 * @implemented
199 */
200 VOID NTAPI
201 CcSetDirtyPinnedData (
202 IN PVOID Bcb,
203 IN PLARGE_INTEGER Lsn)
204 {
205 PINTERNAL_BCB iBcb = Bcb;
206
207 CCTRACE(CC_API_DEBUG, "Bcb=%p Lsn=%p\n",
208 Bcb, Lsn);
209
210 iBcb->Dirty = TRUE;
211 }
212
213
214 /*
215 * @implemented
216 */
217 VOID NTAPI
218 CcUnpinData (
219 IN PVOID Bcb)
220 {
221 PINTERNAL_BCB iBcb = Bcb;
222
223 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
224
225 CcRosReleaseVacb(iBcb->Vacb->SharedCacheMap,
226 iBcb->Vacb,
227 TRUE,
228 iBcb->Dirty,
229 FALSE);
230 if (--iBcb->RefCount == 0)
231 {
232 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
233 }
234 }
235
236 /*
237 * @unimplemented
238 */
239 VOID
240 NTAPI
241 CcUnpinDataForThread (
242 IN PVOID Bcb,
243 IN ERESOURCE_THREAD ResourceThreadId)
244 {
245 PINTERNAL_BCB iBcb = Bcb;
246
247 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
248
249 if (iBcb->OwnerPointer != (PVOID)ResourceThreadId)
250 {
251 DPRINT1("Invalid owner! Caller: %p, Owner: %p\n", (PVOID)ResourceThreadId, iBcb->OwnerPointer);
252 return;
253 }
254
255 return CcUnpinData(Bcb);
256 }
257
258 /*
259 * @implemented
260 */
261 VOID
262 NTAPI
263 CcRepinBcb (
264 IN PVOID Bcb)
265 {
266 PINTERNAL_BCB iBcb = Bcb;
267
268 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
269
270 iBcb->RefCount++;
271 }
272
273 /*
274 * @unimplemented
275 */
276 VOID
277 NTAPI
278 CcUnpinRepinnedBcb (
279 IN PVOID Bcb,
280 IN BOOLEAN WriteThrough,
281 IN PIO_STATUS_BLOCK IoStatus)
282 {
283 PINTERNAL_BCB iBcb = Bcb;
284
285 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
286
287 IoStatus->Status = STATUS_SUCCESS;
288 if (--iBcb->RefCount == 0)
289 {
290 IoStatus->Information = 0;
291 if (WriteThrough)
292 {
293 KeWaitForSingleObject(&iBcb->Vacb->Mutex,
294 Executive,
295 KernelMode,
296 FALSE,
297 NULL);
298 if (iBcb->Vacb->Dirty)
299 {
300 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
301 }
302 else
303 {
304 IoStatus->Status = STATUS_SUCCESS;
305 }
306 KeReleaseMutex(&iBcb->Vacb->Mutex, FALSE);
307 }
308 else
309 {
310 IoStatus->Status = STATUS_SUCCESS;
311 }
312
313 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
314 }
315 }