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