Lots of changes to the kernel
[reactos.git] / reactos / ntoskrnl / cc / view.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/view.c
5 * PURPOSE: Cache manager
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <ddk/ntifs.h>
15 #include <internal/mm.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 /* FUNCTIONS *****************************************************************/
21
22 NTSTATUS CcFlushCachePage(PCACHE_SEGMENT CacheSeg)
23 /*
24 * FUNCTION: Asks the FSD to flush the contents of the page back to disk
25 */
26 {
27 KeWaitForSingleObject(&CacheSeg->Lock,
28 Executive,
29 KernelMode,
30 FALSE,
31 NULL);
32 /* Build an IRP_MJ_WRITE and send it to the filesystem */
33 KeSetEvent(&CacheSeg->Lock, IO_NO_INCREMENT, 0);
34 return(STATUS_NOT_IMPLEMENTED);
35 }
36
37 NTSTATUS CcReleaseCachePage(PBCB Bcb,
38 PCACHE_SEGMENT CacheSeg,
39 BOOLEAN Valid)
40 {
41 DPRINT("CcReleaseCachePage(Bcb %x, CacheSeg %x, Valid %d)\n",
42 Bcb, CacheSeg, Valid);
43
44 CacheSeg->ReferenceCount--;
45 CacheSeg->Valid = Valid;
46 KeSetEvent(&CacheSeg->Lock, IO_NO_INCREMENT, FALSE);
47
48 DPRINT("CcReleaseCachePage() finished\n");
49
50 return(STATUS_SUCCESS);
51 }
52
53 NTSTATUS CcRequestCachePage(PBCB Bcb,
54 ULONG FileOffset,
55 PVOID* BaseAddress,
56 PBOOLEAN UptoDate,
57 PCACHE_SEGMENT* CacheSeg)
58 {
59 KIRQL oldirql;
60 PLIST_ENTRY current_entry;
61 PCACHE_SEGMENT current;
62
63 DPRINT("CcRequestCachePage(Bcb %x, FileOffset %x, BaseAddress %x, "
64 "UptoDate %x, CacheSeg %x)\n", Bcb, FileOffset, BaseAddress,
65 UptoDate, CacheSeg);
66
67 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
68
69 current_entry = Bcb->CacheSegmentListHead.Flink;
70 while (current_entry != &Bcb->CacheSegmentListHead)
71 {
72 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, ListEntry);
73 if (current->FileOffset == PAGE_ROUND_DOWN(FileOffset))
74 {
75 DPRINT("Found existing segment at %x\n", current);
76 current->ReferenceCount++;
77 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
78 DPRINT("Waiting for segment\n");
79 KeWaitForSingleObject(&current->Lock,
80 Executive,
81 KernelMode,
82 FALSE,
83 NULL);
84 *UptoDate = current->Valid;
85 *BaseAddress = current->BaseAddress;
86 *CacheSeg = current;
87 DPRINT("Returning %x (UptoDate %d)\n", current, current->Valid);
88 return(STATUS_SUCCESS);
89 }
90 current_entry = current_entry->Flink;
91 }
92
93 DPRINT("Creating new segment\n");
94
95 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
96
97 current = ExAllocatePool(NonPagedPool, sizeof(CACHE_SEGMENT));
98 current->BaseAddress = NULL;
99 MmCreateMemoryArea(KernelMode,
100 NULL,
101 MEMORY_AREA_CACHE_SEGMENT,
102 &current->BaseAddress,
103 CACHE_SEGMENT_SIZE,
104 PAGE_READWRITE,
105 (PMEMORY_AREA*)&current->MemoryArea);
106 CHECKPOINT;
107 current->Valid = FALSE;
108 current->FileOffset = PAGE_ROUND_DOWN(FileOffset);
109 current->Bcb = Bcb;
110 CHECKPOINT;
111 KeInitializeEvent(&current->Lock, SynchronizationEvent, FALSE);
112 current->ReferenceCount = 1;
113 CHECKPOINT;
114 InsertTailList(&Bcb->CacheSegmentListHead, &current->ListEntry);
115 CHECKPOINT;
116 *UptoDate = current->Valid;
117 *BaseAddress = current->BaseAddress;
118 *CacheSeg = current;
119 CHECKPOINT;
120 MmSetPage(NULL,
121 current->BaseAddress,
122 PAGE_READWRITE,
123 (ULONG)MmAllocPage());
124
125
126 DPRINT("Returning %x (BaseAddress %x)\n", current, *BaseAddress);
127
128 return(STATUS_SUCCESS);
129 }
130
131 NTSTATUS CcFreeCacheSegment(PFILE_OBJECT FileObject,
132 PBCB Bcb,
133 PCACHE_SEGMENT CacheSeg)
134 {
135 MmFreeMemoryArea(NULL,
136 CacheSeg->BaseAddress,
137 CACHE_SEGMENT_SIZE,
138 TRUE);
139 ExFreePool(CacheSeg);
140 return(STATUS_SUCCESS);
141 }
142
143 NTSTATUS CcReleaseFileCache(PFILE_OBJECT FileObject,
144 PBCB Bcb)
145 {
146 PLIST_ENTRY current_entry;
147 PCACHE_SEGMENT current;
148
149 DPRINT("CcReleaseFileCache(FileObject %x, Bcb %x)\n",
150 FileObject, Bcb);
151
152 current_entry = Bcb->CacheSegmentListHead.Flink;
153 while (current_entry != (&Bcb->CacheSegmentListHead))
154 {
155 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, ListEntry);
156 current_entry = current_entry->Flink;
157 CcFreeCacheSegment(FileObject,
158 Bcb,
159 current);
160 }
161
162 ExFreePool(Bcb);
163
164 DPRINT("CcReleaseFileCache() finished\n");
165
166 return(STATUS_SUCCESS);
167 }
168
169 NTSTATUS CcInitializeFileCache(PFILE_OBJECT FileObject,
170 PBCB* Bcb)
171 {
172 DPRINT("CcInitializeFileCache(FileObject %x)\n",FileObject);
173
174 (*Bcb) = ExAllocatePool(NonPagedPool, sizeof(BCB));
175 if ((*Bcb) == NULL)
176 {
177 return(STATUS_UNSUCCESSFUL);
178 }
179
180 (*Bcb)->FileObject = FileObject;
181 InitializeListHead(&(*Bcb)->CacheSegmentListHead);
182 KeInitializeSpinLock(&(*Bcb)->BcbLock);
183
184 DPRINT("Finished CcInitializeFileCache() = %x\n", *Bcb);
185
186 return(STATUS_SUCCESS);
187 }
188
189
190