Merge 13831:14550 from trunk
[reactos.git] / reactos / ntoskrnl / cc / fs.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cc/fs.c
6 * PURPOSE: Implements cache managers functions useful for File Systems
7 *
8 * PROGRAMMERS: Alex Ionescu
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 #ifndef VACB_MAPPING_GRANULARITY
18 #define VACB_MAPPING_GRANULARITY (256 * 1024)
19 #endif
20
21 /* GLOBALS *****************************************************************/
22
23 extern FAST_MUTEX ViewLock;
24 extern ULONG DirtyPageCount;
25
26 NTSTATUS CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
27
28 /* FUNCTIONS *****************************************************************/
29
30 /*
31 * @unimplemented
32 */
33 LARGE_INTEGER
34 STDCALL
35 CcGetDirtyPages (
36 IN PVOID LogHandle,
37 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
38 IN PVOID Context1,
39 IN PVOID Context2
40 )
41 {
42 UNIMPLEMENTED;
43
44 LARGE_INTEGER i;
45 i.QuadPart = 0;
46 return i;
47 }
48
49 /*
50 * @implemented
51 */
52 PFILE_OBJECT
53 STDCALL
54 CcGetFileObjectFromBcb (
55 IN PVOID Bcb
56 )
57 {
58 PINTERNAL_BCB iBcb = (PINTERNAL_BCB)Bcb;
59 return iBcb->CacheSegment->Bcb->FileObject;
60 }
61
62 /*
63 * @unimplemented
64 */
65 LARGE_INTEGER
66 STDCALL
67 CcGetLsnForFileObject (
68 IN PFILE_OBJECT FileObject,
69 OUT PLARGE_INTEGER OldestLsn OPTIONAL
70 )
71 {
72 UNIMPLEMENTED;
73
74 LARGE_INTEGER i;
75 i.QuadPart = 0;
76 return i;
77 }
78
79 /*
80 * @unimplemented
81 */
82 VOID
83 STDCALL
84 CcInitializeCacheMap (
85 IN PFILE_OBJECT FileObject,
86 IN PCC_FILE_SIZES FileSizes,
87 IN BOOLEAN PinAccess,
88 IN PCACHE_MANAGER_CALLBACKS CallBacks,
89 IN PVOID LazyWriterContext
90 )
91 {
92 CcRosInitializeFileCache(FileObject, VACB_MAPPING_GRANULARITY);
93 }
94
95 /*
96 * @unimplemented
97 */
98 BOOLEAN
99 STDCALL
100 CcIsThereDirtyData (
101 IN PVPB Vpb
102 )
103 {
104 UNIMPLEMENTED;
105 return FALSE;
106 }
107
108 /*
109 * @unimplemented
110 */
111 BOOLEAN
112 STDCALL
113 CcPurgeCacheSection (
114 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
115 IN PLARGE_INTEGER FileOffset OPTIONAL,
116 IN ULONG Length,
117 IN BOOLEAN UninitializeCacheMaps
118 )
119 {
120 UNIMPLEMENTED;
121 return FALSE;
122 }
123
124
125 /*
126 * @implemented
127 */
128 VOID STDCALL
129 CcSetFileSizes (IN PFILE_OBJECT FileObject,
130 IN PCC_FILE_SIZES FileSizes)
131 {
132 KIRQL oldirql;
133 PBCB Bcb;
134 PLIST_ENTRY current_entry;
135 PCACHE_SEGMENT current;
136 LIST_ENTRY FreeListHead;
137 NTSTATUS Status;
138
139 DPRINT("CcSetFileSizes(FileObject %x, FileSizes %x)\n",
140 FileObject, FileSizes);
141 DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
142 (ULONG)FileSizes->AllocationSize.QuadPart,
143 (ULONG)FileSizes->FileSize.QuadPart,
144 (ULONG)FileSizes->ValidDataLength.QuadPart);
145
146 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
147
148 /*
149 * It is valid to call this function on file objects that weren't
150 * initialized for caching. In this case it's simple no-op.
151 */
152 if (Bcb == NULL)
153 return;
154
155 if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
156 {
157 InitializeListHead(&FreeListHead);
158 ExAcquireFastMutex(&ViewLock);
159 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
160
161 current_entry = Bcb->BcbSegmentListHead.Flink;
162 while (current_entry != &Bcb->BcbSegmentListHead)
163 {
164 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 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 -= Bcb->CacheSegmentSize / 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 KEBUGCHECKCC;
184 }
185 }
186 }
187
188 Bcb->AllocationSize = FileSizes->AllocationSize;
189 Bcb->FileSize = FileSizes->FileSize;
190 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
191 ExReleaseFastMutex(&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");
202 KEBUGCHECK(0);
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 STDCALL
220 CcSetLogHandleForFile (
221 IN PFILE_OBJECT FileObject,
222 IN PVOID LogHandle,
223 IN PFLUSH_TO_LSN FlushToLsnRoutine
224 )
225 {
226 UNIMPLEMENTED;
227 }
228
229 /*
230 * @unimplemented
231 */
232 BOOLEAN
233 STDCALL
234 CcUninitializeCacheMap (
235 IN PFILE_OBJECT FileObject,
236 IN PLARGE_INTEGER TruncateSize OPTIONAL,
237 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
238 )
239 {
240 #if 0
241 UNIMPLEMENTED;
242 return FALSE;
243 #else
244 return CcRosReleaseFileCache(FileObject);
245 #endif
246 }