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