[NTOS:CC]
[reactos.git] / reactos / 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 LARGE_INTEGER i;
41 UNIMPLEMENTED;
42 i.QuadPart = 0;
43 return i;
44 }
45
46 /*
47 * @implemented
48 */
49 PFILE_OBJECT
50 NTAPI
51 CcGetFileObjectFromBcb (
52 IN PVOID Bcb)
53 {
54 PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
55 return iBcb->CacheSegment->Bcb->FileObject;
56 }
57
58 /*
59 * @unimplemented
60 */
61 LARGE_INTEGER
62 NTAPI
63 CcGetLsnForFileObject (
64 IN PFILE_OBJECT FileObject,
65 OUT PLARGE_INTEGER OldestLsn OPTIONAL)
66 {
67 LARGE_INTEGER i;
68 UNIMPLEMENTED;
69 i.QuadPart = 0;
70 return i;
71 }
72
73 /*
74 * @unimplemented
75 */
76 VOID
77 NTAPI
78 CcInitializeCacheMap (
79 IN PFILE_OBJECT FileObject,
80 IN PCC_FILE_SIZES FileSizes,
81 IN BOOLEAN PinAccess,
82 IN PCACHE_MANAGER_CALLBACKS CallBacks,
83 IN PVOID LazyWriterContext)
84 {
85 ASSERT(FileObject);
86 ASSERT(FileSizes);
87
88 /* Call old ROS cache init function */
89 CcRosInitializeFileCache(FileObject,
90 CallBacks,
91 LazyWriterContext);
92 }
93
94 /*
95 * @unimplemented
96 */
97 BOOLEAN
98 NTAPI
99 CcIsThereDirtyData (
100 IN PVPB Vpb)
101 {
102 UNIMPLEMENTED;
103 return FALSE;
104 }
105
106 /*
107 * @unimplemented
108 */
109 BOOLEAN
110 NTAPI
111 CcPurgeCacheSection (
112 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
113 IN PLARGE_INTEGER FileOffset OPTIONAL,
114 IN ULONG Length,
115 IN BOOLEAN UninitializeCacheMaps)
116 {
117 //UNIMPLEMENTED;
118 return FALSE;
119 }
120
121
122 /*
123 * @implemented
124 */
125 VOID NTAPI
126 CcSetFileSizes (
127 IN PFILE_OBJECT FileObject,
128 IN PCC_FILE_SIZES FileSizes)
129 {
130 KIRQL oldirql;
131 PBCB Bcb;
132 PLIST_ENTRY current_entry;
133 PCACHE_SEGMENT current;
134 LIST_ENTRY FreeListHead;
135 NTSTATUS Status;
136
137 DPRINT("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n",
138 FileObject, FileSizes);
139 DPRINT("AllocationSize %I64d, FileSize %I64d, ValidDataLength %I64d\n",
140 FileSizes->AllocationSize.QuadPart,
141 FileSizes->FileSize.QuadPart,
142 FileSizes->ValidDataLength.QuadPart);
143
144 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
145
146 /*
147 * It is valid to call this function on file objects that weren't
148 * initialized for caching. In this case it's simple no-op.
149 */
150 if (Bcb == NULL)
151 return;
152
153 if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
154 {
155 InitializeListHead(&FreeListHead);
156 KeAcquireGuardedMutex(&ViewLock);
157 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
158
159 current_entry = Bcb->BcbSegmentListHead.Flink;
160 while (current_entry != &Bcb->BcbSegmentListHead)
161 {
162 current = CONTAINING_RECORD(current_entry,
163 CACHE_SEGMENT,
164 BcbSegmentListEntry);
165 current_entry = current_entry->Flink;
166 if (current->FileOffset >= FileSizes->AllocationSize.QuadPart)
167 {
168 if ((current->ReferenceCount == 0) || ((current->ReferenceCount == 1) && current->Dirty))
169 {
170 RemoveEntryList(&current->BcbSegmentListEntry);
171 RemoveEntryList(&current->CacheSegmentListEntry);
172 RemoveEntryList(&current->CacheSegmentLRUListEntry);
173 if (current->Dirty)
174 {
175 RemoveEntryList(&current->DirtySegmentListEntry);
176 DirtyPageCount -= VACB_MAPPING_GRANULARITY / PAGE_SIZE;
177 }
178 InsertHeadList(&FreeListHead, &current->BcbSegmentListEntry);
179 }
180 else
181 {
182 DPRINT1("Anyone has referenced a cache segment behind the new size.\n");
183 KeBugCheck(CACHE_MANAGER);
184 }
185 }
186 }
187
188 Bcb->AllocationSize = FileSizes->AllocationSize;
189 Bcb->FileSize = FileSizes->FileSize;
190 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
191 KeReleaseGuardedMutex(&ViewLock);
192
193 current_entry = FreeListHead.Flink;
194 while(current_entry != &FreeListHead)
195 {
196 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
197 current_entry = current_entry->Flink;
198 Status = CcRosInternalFreeCacheSegment(current);
199 if (!NT_SUCCESS(Status))
200 {
201 DPRINT1("CcRosInternalFreeCacheSegment failed, status = %x\n", Status);
202 KeBugCheck(CACHE_MANAGER);
203 }
204 }
205 }
206 else
207 {
208 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
209 Bcb->AllocationSize = FileSizes->AllocationSize;
210 Bcb->FileSize = FileSizes->FileSize;
211 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
212 }
213 }
214
215 /*
216 * @unimplemented
217 */
218 VOID
219 NTAPI
220 CcSetLogHandleForFile (
221 IN PFILE_OBJECT FileObject,
222 IN PVOID LogHandle,
223 IN PFLUSH_TO_LSN FlushToLsnRoutine)
224 {
225 UNIMPLEMENTED;
226 }
227
228 /*
229 * @unimplemented
230 */
231 BOOLEAN
232 NTAPI
233 CcUninitializeCacheMap (
234 IN PFILE_OBJECT FileObject,
235 IN PLARGE_INTEGER TruncateSize OPTIONAL,
236 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL)
237 {
238 #if 0
239 UNIMPLEMENTED;
240 return FALSE;
241 #else
242 return NT_SUCCESS(CcRosReleaseFileCache(FileObject));
243 #endif
244 }
245
246 BOOLEAN
247 NTAPI
248 CcGetFileSizes (
249 IN PFILE_OBJECT FileObject,
250 IN PCC_FILE_SIZES FileSizes)
251 {
252 PBCB Bcb;
253
254 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
255
256 if (!Bcb)
257 return FALSE;
258
259 FileSizes->AllocationSize = Bcb->AllocationSize;
260 FileSizes->FileSize = FileSizes->ValidDataLength = Bcb->FileSize;
261 return TRUE;
262 }