[CLT2012]
[reactos.git] / ntoskrnl / cc / fs.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/fs.c
5 * PURPOSE: Implements cache managers functions useful for File Systems
6 *
7 * PROGRAMMERS: Alex Ionescu
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #ifndef VACB_MAPPING_GRANULARITY
17 #define VACB_MAPPING_GRANULARITY (256 * 1024)
18 #endif
19
20 /* GLOBALS *****************************************************************/
21
22 extern KGUARDED_MUTEX ViewLock;
23 extern ULONG DirtyPageCount;
24
25 NTSTATUS CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
26
27 /* FUNCTIONS *****************************************************************/
28
29 /*
30 * @unimplemented
31 */
32 LARGE_INTEGER
33 NTAPI
34 CcGetDirtyPages (
35 IN PVOID LogHandle,
36 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
37 IN PVOID Context1,
38 IN PVOID Context2
39 )
40 {
41 LARGE_INTEGER i;
42 UNIMPLEMENTED;
43 i.QuadPart = 0;
44 return i;
45 }
46
47 /*
48 * @implemented
49 */
50 PFILE_OBJECT
51 NTAPI
52 CcGetFileObjectFromBcb (
53 IN PVOID Bcb
54 )
55 {
56 PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
57 return iBcb->CacheSegment->Bcb->FileObject;
58 }
59
60 /*
61 * @unimplemented
62 */
63 LARGE_INTEGER
64 NTAPI
65 CcGetLsnForFileObject (
66 IN PFILE_OBJECT FileObject,
67 OUT PLARGE_INTEGER OldestLsn OPTIONAL
68 )
69 {
70 LARGE_INTEGER i;
71 UNIMPLEMENTED;
72 i.QuadPart = 0;
73 return i;
74 }
75
76 /*
77 * @unimplemented
78 */
79 VOID
80 NTAPI
81 CcInitializeCacheMap (
82 IN PFILE_OBJECT FileObject,
83 IN PCC_FILE_SIZES FileSizes,
84 IN BOOLEAN PinAccess,
85 IN PCACHE_MANAGER_CALLBACKS CallBacks,
86 IN PVOID LazyWriterContext
87 )
88 {
89 ASSERT(FileObject);
90 ASSERT(FileSizes);
91
92 /* Call old ROS cache init function */
93 CcRosInitializeFileCache(FileObject,
94 /*PAGE_SIZE*/ VACB_MAPPING_GRANULARITY, CallBacks,
95 LazyWriterContext);
96 }
97
98 /*
99 * @unimplemented
100 */
101 BOOLEAN
102 NTAPI
103 CcIsThereDirtyData (
104 IN PVPB Vpb
105 )
106 {
107 UNIMPLEMENTED;
108 return FALSE;
109 }
110
111 /*
112 * @unimplemented
113 */
114 BOOLEAN
115 NTAPI
116 CcPurgeCacheSection (
117 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
118 IN PLARGE_INTEGER FileOffset OPTIONAL,
119 IN ULONG Length,
120 IN BOOLEAN UninitializeCacheMaps
121 )
122 {
123 //UNIMPLEMENTED;
124 return FALSE;
125 }
126
127
128 /*
129 * @implemented
130 */
131 VOID NTAPI
132 CcSetFileSizes (IN PFILE_OBJECT FileObject,
133 IN PCC_FILE_SIZES FileSizes)
134 {
135 KIRQL oldirql;
136 PBCB Bcb;
137 PLIST_ENTRY current_entry;
138 PCACHE_SEGMENT current;
139 LIST_ENTRY FreeListHead;
140 NTSTATUS Status;
141
142 DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
143 FileObject, FileSizes);
144 DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
145 (ULONG)FileSizes->AllocationSize.QuadPart,
146 (ULONG)FileSizes->FileSize.QuadPart,
147 (ULONG)FileSizes->ValidDataLength.QuadPart);
148
149 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
150
151 /*
152 * It is valid to call this function on file objects that weren't
153 * initialized for caching. In this case it's simple no-op.
154 */
155 if (Bcb == NULL)
156 return;
157
158 if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
159 {
160 InitializeListHead(&FreeListHead);
161 KeAcquireGuardedMutex(&ViewLock);
162 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
163
164 current_entry = Bcb->BcbSegmentListHead.Flink;
165 while (current_entry != &Bcb->BcbSegmentListHead)
166 {
167 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
168 current_entry = current_entry->Flink;
169 if (current->FileOffset > FileSizes->AllocationSize.QuadPart ||
170 (current->FileOffset == 0 && FileSizes->AllocationSize.QuadPart == 0))
171 {
172 if (current->ReferenceCount == 0 || (current->ReferenceCount == 1 && current->Dirty))
173 {
174 RemoveEntryList(&current->BcbSegmentListEntry);
175 RemoveEntryList(&current->CacheSegmentListEntry);
176 RemoveEntryList(&current->CacheSegmentLRUListEntry);
177 if (current->Dirty)
178 {
179 RemoveEntryList(&current->DirtySegmentListEntry);
180 DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE;
181 }
182 InsertHeadList(&FreeListHead, &current->BcbSegmentListEntry);
183 }
184 else
185 {
186 DPRINT1("Anyone has referenced a cache segment behind the new size.\n");
187 KeBugCheck(CACHE_MANAGER);
188 }
189 }
190 }
191
192 Bcb->AllocationSize = FileSizes->AllocationSize;
193 Bcb->FileSize = FileSizes->FileSize;
194 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
195 KeReleaseGuardedMutex(&ViewLock);
196
197 current_entry = FreeListHead.Flink;
198 while(current_entry != &FreeListHead)
199 {
200 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
201 current_entry = current_entry->Flink;
202 Status = CcRosInternalFreeCacheSegment(current);
203 if (!NT_SUCCESS(Status))
204 {
205 DPRINT1("CcRosInternalFreeCacheSegment failed, status = %x\n", Status);
206 KeBugCheck(CACHE_MANAGER);
207 }
208 }
209 }
210 else
211 {
212 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
213 Bcb->AllocationSize = FileSizes->AllocationSize;
214 Bcb->FileSize = FileSizes->FileSize;
215 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
216 }
217 }
218
219 /*
220 * @unimplemented
221 */
222 VOID
223 NTAPI
224 CcSetLogHandleForFile (
225 IN PFILE_OBJECT FileObject,
226 IN PVOID LogHandle,
227 IN PFLUSH_TO_LSN FlushToLsnRoutine
228 )
229 {
230 UNIMPLEMENTED;
231 }
232
233 /*
234 * @unimplemented
235 */
236 BOOLEAN
237 NTAPI
238 CcUninitializeCacheMap (
239 IN PFILE_OBJECT FileObject,
240 IN PLARGE_INTEGER TruncateSize OPTIONAL,
241 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
242 )
243 {
244 #if 0
245 UNIMPLEMENTED;
246 return FALSE;
247 #else
248 return NT_SUCCESS(CcRosReleaseFileCache(FileObject));
249 #endif
250 }