af0e357be746025afb12f3c878991a585ce61789
[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 CCTRACE(CC_API_DEBUG, "Bcb=%p ResourceThreadId=%lu\n", Bcb, ResourceThreadId);
246
247 UNIMPLEMENTED;
248 }
249
250 /*
251 * @implemented
252 */
253 VOID
254 NTAPI
255 CcRepinBcb (
256 IN PVOID Bcb)
257 {
258 PINTERNAL_BCB iBcb = Bcb;
259
260 CCTRACE(CC_API_DEBUG, "Bcb=%p\n", Bcb);
261
262 iBcb->RefCount++;
263 }
264
265 /*
266 * @unimplemented
267 */
268 VOID
269 NTAPI
270 CcUnpinRepinnedBcb (
271 IN PVOID Bcb,
272 IN BOOLEAN WriteThrough,
273 IN PIO_STATUS_BLOCK IoStatus)
274 {
275 PINTERNAL_BCB iBcb = Bcb;
276
277 CCTRACE(CC_API_DEBUG, "Bcb=%p WriteThrough=%d\n", Bcb, WriteThrough);
278
279 IoStatus->Status = STATUS_SUCCESS;
280 if (--iBcb->RefCount == 0)
281 {
282 IoStatus->Information = 0;
283 if (WriteThrough)
284 {
285 KeWaitForSingleObject(&iBcb->Vacb->Mutex,
286 Executive,
287 KernelMode,
288 FALSE,
289 NULL);
290 if (iBcb->Vacb->Dirty)
291 {
292 IoStatus->Status = CcRosFlushVacb(iBcb->Vacb);
293 }
294 else
295 {
296 IoStatus->Status = STATUS_SUCCESS;
297 }
298 KeReleaseMutex(&iBcb->Vacb->Mutex, FALSE);
299 }
300 else
301 {
302 IoStatus->Status = STATUS_SUCCESS;
303 }
304
305 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
306 }
307 }