de20a1ae947950a4e5bb5ce436542133fba1bff1
[reactos.git] / reactos / ntoskrnl / cc / pin.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cc/pin.c
6 * PURPOSE: Implements cache managers pinning interface
7 * PROGRAMMER: Hartmut Birr
8 * UPDATE HISTORY:
9 * Created 05.10.2001
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
21
22 extern NPAGED_LOOKASIDE_LIST iBcbLookasideList;
23
24 /* FUNCTIONS *****************************************************************/
25
26 /*
27 * @implemented
28 */
29 BOOLEAN STDCALL
30 CcMapData (IN PFILE_OBJECT FileObject,
31 IN PLARGE_INTEGER FileOffset,
32 IN ULONG Length,
33 IN BOOLEAN Wait,
34 OUT PVOID *pBcb,
35 OUT PVOID *pBuffer)
36 {
37 ULONG ReadOffset;
38 BOOLEAN Valid;
39 PBCB Bcb;
40 PCACHE_SEGMENT CacheSeg;
41 NTSTATUS Status;
42 PINTERNAL_BCB iBcb;
43 ULONG ROffset;
44
45 DPRINT("CcMapData(FileObject %x, FileOffset %d, Length %d, Wait %d,"
46 " pBcb %x, pBuffer %x)\n", FileObject, (ULONG)FileOffset->QuadPart,
47 Length, Wait, pBcb, pBuffer);
48
49 ReadOffset = (ULONG)FileOffset->QuadPart;
50 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
51 ASSERT(Bcb);
52
53 DPRINT("AllocationSize %d, FileSize %d\n",
54 (ULONG)Bcb->AllocationSize.QuadPart,
55 (ULONG)Bcb->FileSize.QuadPart);
56
57 if (ReadOffset % Bcb->CacheSegmentSize + Length > Bcb->CacheSegmentSize)
58 {
59 return(FALSE);
60 }
61 ROffset = ROUND_DOWN (ReadOffset, Bcb->CacheSegmentSize);
62 Status = CcRosRequestCacheSegment(Bcb,
63 ROffset,
64 pBuffer,
65 &Valid,
66 &CacheSeg);
67 if (!NT_SUCCESS(Status))
68 {
69 return(FALSE);
70 }
71 if (!Valid)
72 {
73 if (!Wait)
74 {
75 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
76 return(FALSE);
77 }
78 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
79 {
80 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
81 return(FALSE);
82 }
83 }
84 #if defined(__GNUC__)
85 *pBuffer += ReadOffset % Bcb->CacheSegmentSize;
86 #else
87 {
88 char* pTemp = *pBuffer;
89 pTemp += ReadOffset % Bcb->CacheSegmentSize;
90 *pBuffer = pTemp;
91 }
92 #endif
93 iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList);
94 if (iBcb == NULL)
95 {
96 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
97 return FALSE;
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 return(TRUE);
109 }
110
111 /*
112 * @unimplemented
113 */
114 BOOLEAN
115 STDCALL
116 CcPinMappedData (
117 IN PFILE_OBJECT FileObject,
118 IN PLARGE_INTEGER FileOffset,
119 IN ULONG Length,
120 IN ULONG Flags,
121 OUT PVOID * Bcb
122 )
123 {
124 /* no-op for current implementation. */
125 return TRUE;
126 }
127
128 /*
129 * @unimplemented
130 */
131 BOOLEAN
132 STDCALL
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 {
142 if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer))
143 {
144 if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb))
145 return TRUE;
146 else
147 CcUnpinData(Bcb);
148 }
149 return FALSE;
150 }
151
152 /*
153 * @unimplemented
154 */
155 BOOLEAN
156 STDCALL
157 CcPreparePinWrite (
158 IN PFILE_OBJECT FileObject,
159 IN PLARGE_INTEGER FileOffset,
160 IN ULONG Length,
161 IN BOOLEAN Zero,
162 IN ULONG Flags,
163 OUT PVOID * Bcb,
164 OUT PVOID * Buffer
165 )
166 {
167 /*
168 * FIXME: This is function is similar to CcPinRead, but doesn't
169 * read the data if they're not present. Instead it should just
170 * prepare the cache segments and zero them out if Zero == TRUE.
171 *
172 * For now calling CcPinRead is better than returning error or
173 * just having UNIMPLEMENTED here.
174 */
175 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer);
176 }
177
178 /*
179 * @implemented
180 */
181 VOID STDCALL
182 CcSetDirtyPinnedData (IN PVOID Bcb,
183 IN PLARGE_INTEGER Lsn)
184 {
185 PINTERNAL_BCB iBcb = Bcb;
186 iBcb->Dirty = TRUE;
187 }
188
189
190 /*
191 * @implemented
192 */
193 VOID STDCALL
194 CcUnpinData (IN PVOID Bcb)
195 {
196 PINTERNAL_BCB iBcb = Bcb;
197 CcRosReleaseCacheSegment(iBcb->CacheSegment->Bcb, iBcb->CacheSegment, TRUE,
198 iBcb->Dirty, FALSE);
199 if (--iBcb->RefCount == 0)
200 {
201 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
202 }
203 }
204
205 /*
206 * @unimplemented
207 */
208 VOID
209 STDCALL
210 CcUnpinDataForThread (
211 IN PVOID Bcb,
212 IN ERESOURCE_THREAD ResourceThreadId
213 )
214 {
215 UNIMPLEMENTED;
216 }
217
218 /*
219 * @implemented
220 */
221 VOID
222 STDCALL
223 CcRepinBcb (
224 IN PVOID Bcb
225 )
226 {
227 PINTERNAL_BCB iBcb = Bcb;
228 iBcb->RefCount++;
229 }
230
231 /*
232 * @unimplemented
233 */
234 VOID
235 STDCALL
236 CcUnpinRepinnedBcb (
237 IN PVOID Bcb,
238 IN BOOLEAN WriteThrough,
239 IN PIO_STATUS_BLOCK IoStatus
240 )
241 {
242 PINTERNAL_BCB iBcb = Bcb;
243
244 if (--iBcb->RefCount == 0)
245 {
246 IoStatus->Information = 0;
247 if (WriteThrough)
248 {
249 ExAcquireFastMutex(&iBcb->CacheSegment->Lock);
250 if (iBcb->CacheSegment->Dirty)
251 {
252 IoStatus->Status = CcRosFlushCacheSegment(iBcb->CacheSegment);
253 }
254 else
255 {
256 IoStatus->Status = STATUS_SUCCESS;
257 }
258 ExReleaseFastMutex(&iBcb->CacheSegment->Lock);
259 }
260 else
261 {
262 IoStatus->Status = STATUS_SUCCESS;
263 }
264
265 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb);
266 }
267 }