254c25c38a6e4dfb4c82080a04965bf6ac8dc515
[reactos.git] / reactos / ntoskrnl / cache / section / io.c
1 /*
2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 *
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/mm/section.c
21 * PURPOSE: Implements section objects
22 *
23 * PROGRAMMERS: Rex Jolliff
24 * David Welch
25 * Eric Kohl
26 * Emanuele Aliberti
27 * Eugene Ingerman
28 * Casper Hornstrup
29 * KJK::Hyperion
30 * Guido de Jong
31 * Ge van Geldorp
32 * Royce Mitchell III
33 * Filip Navara
34 * Aleksey Bragin
35 * Jason Filby
36 * Thomas Weidenmueller
37 * Gunnar Andre' Dalsnes
38 * Mike Nordell
39 * Alex Ionescu
40 * Gregor Anich
41 * Steven Edwards
42 * Herve Poussineau
43 */
44
45 /* INCLUDES *****************************************************************/
46
47 #include <ntoskrnl.h>
48 #include "newmm.h"
49 #define NDEBUG
50 #include <debug.h>
51 #include <reactos/exeformat.h>
52
53 #if defined (ALLOC_PRAGMA)
54 #pragma alloc_text(INIT, MmCreatePhysicalMemorySection)
55 #pragma alloc_text(INIT, MmInitSectionImplementation)
56 #endif
57
58 KEVENT CcpLazyWriteEvent;
59
60 PDEVICE_OBJECT
61 NTAPI
62 MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject)
63 {
64 return IoGetRelatedDeviceObject(FileObject);
65 }
66
67 NTSTATUS
68 NTAPI
69 MiSimpleReadComplete
70 (PDEVICE_OBJECT DeviceObject,
71 PIRP Irp,
72 PVOID Context)
73 {
74 /* Unlock MDL Pages, page 167. */
75 DPRINT("MiSimpleReadComplete %x\n", Irp);
76 PMDL Mdl = Irp->MdlAddress;
77 while (Mdl)
78 {
79 DPRINT("MDL Unlock %x\n", Mdl);
80 MmUnlockPages(Mdl);
81 Mdl = Mdl->Next;
82 }
83
84 /* Check if there's an MDL */
85 while ((Mdl = Irp->MdlAddress))
86 {
87 /* Clear all of them */
88 Irp->MdlAddress = Mdl->Next;
89 IoFreeMdl(Mdl);
90 }
91
92 return STATUS_SUCCESS;
93 }
94
95 NTSTATUS
96 NTAPI
97 MiSimpleRead
98 (PFILE_OBJECT FileObject,
99 PLARGE_INTEGER FileOffset,
100 PVOID Buffer,
101 ULONG Length,
102 PIO_STATUS_BLOCK ReadStatus)
103 {
104 NTSTATUS Status;
105 PIRP Irp = NULL;
106 KEVENT ReadWait;
107 PDEVICE_OBJECT DeviceObject;
108 PIO_STACK_LOCATION IrpSp;
109
110 ASSERT(FileObject);
111 ASSERT(FileOffset);
112 ASSERT(Buffer);
113 ASSERT(ReadStatus);
114
115 DeviceObject = MmGetDeviceObjectForFile(FileObject);
116 ReadStatus->Status = STATUS_INTERNAL_ERROR;
117 ReadStatus->Information = 0;
118
119 ASSERT(DeviceObject);
120
121 DPRINT
122 ("PAGING READ: FileObject %x <%wZ> Offset %08x%08x Length %d\n",
123 &FileObject,
124 &FileObject->FileName,
125 FileOffset->HighPart,
126 FileOffset->LowPart,
127 Length);
128
129 KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
130
131 Irp = IoBuildAsynchronousFsdRequest
132 (IRP_MJ_READ,
133 DeviceObject,
134 Buffer,
135 Length,
136 FileOffset,
137 ReadStatus);
138
139 if (!Irp)
140 {
141 return STATUS_NO_MEMORY;
142 }
143
144 Irp->Flags |= IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;
145
146 Irp->UserEvent = &ReadWait;
147 Irp->Tail.Overlay.OriginalFileObject = FileObject;
148 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
149 IrpSp = IoGetNextIrpStackLocation(Irp);
150 IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
151 IrpSp->FileObject = FileObject;
152 IrpSp->CompletionRoutine = MiSimpleReadComplete;
153
154 Status = IoCallDriver(DeviceObject, Irp);
155 if (Status == STATUS_PENDING)
156 {
157 DPRINT1("KeWaitForSingleObject(&ReadWait)\n");
158 if (!NT_SUCCESS
159 (KeWaitForSingleObject
160 (&ReadWait,
161 Suspended,
162 KernelMode,
163 FALSE,
164 NULL)))
165 {
166 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
167 ASSERT(FALSE);
168 return Status;
169 }
170 }
171
172 DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
173 Status =
174 ReadStatus->Status == STATUS_END_OF_FILE ?
175 STATUS_SUCCESS : ReadStatus->Status;
176 return Status;
177 }
178
179 NTSTATUS
180 NTAPI
181 _MiSimpleWrite
182 (PFILE_OBJECT FileObject,
183 PLARGE_INTEGER FileOffset,
184 PVOID Buffer,
185 ULONG Length,
186 PIO_STATUS_BLOCK ReadStatus,
187 const char *File,
188 int Line)
189 {
190 NTSTATUS Status;
191 PIRP Irp = NULL;
192 KEVENT ReadWait;
193 PDEVICE_OBJECT DeviceObject;
194 PIO_STACK_LOCATION IrpSp;
195
196 ASSERT(FileObject);
197 ASSERT(FileOffset);
198 ASSERT(Buffer);
199 ASSERT(ReadStatus);
200
201 ObReferenceObject(FileObject);
202 DeviceObject = MmGetDeviceObjectForFile(FileObject);
203 ASSERT(DeviceObject);
204
205 DPRINT
206 ("PAGING WRITE: FileObject %x Offset %x Length %d (%s:%d)\n",
207 &FileObject,
208 FileOffset->LowPart,
209 Length,
210 File,
211 Line);
212
213 KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
214
215 Irp = IoBuildAsynchronousFsdRequest
216 (IRP_MJ_WRITE,
217 DeviceObject,
218 Buffer,
219 Length,
220 FileOffset,
221 ReadStatus);
222
223 if (!Irp)
224 {
225 ObDereferenceObject(FileObject);
226 return STATUS_NO_MEMORY;
227 }
228
229 Irp->Flags = IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;
230
231 Irp->UserEvent = &ReadWait;
232 Irp->Tail.Overlay.OriginalFileObject = FileObject;
233 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
234 IrpSp = IoGetNextIrpStackLocation(Irp);
235 IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
236 IrpSp->FileObject = FileObject;
237 IrpSp->CompletionRoutine = MiSimpleReadComplete;
238
239 DPRINT("Call Driver\n");
240 Status = IoCallDriver(DeviceObject, Irp);
241 DPRINT("Status %x\n", Status);
242
243 ObDereferenceObject(FileObject);
244
245 if (Status == STATUS_PENDING)
246 {
247 DPRINT1("KeWaitForSingleObject(&ReadWait)\n");
248 if (!NT_SUCCESS
249 (KeWaitForSingleObject
250 (&ReadWait,
251 Suspended,
252 KernelMode,
253 FALSE,
254 NULL)))
255 {
256 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
257 ASSERT(FALSE);
258 return Status;
259 }
260 }
261
262 DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
263 return ReadStatus->Status;
264 }
265
266 extern KEVENT MpwThreadEvent;
267 FAST_MUTEX MiWriteMutex;
268
269 NTSTATUS
270 NTAPI
271 _MiWriteBackPage
272 (PFILE_OBJECT FileObject,
273 PLARGE_INTEGER FileOffset,
274 ULONG Length,
275 PFN_NUMBER Page,
276 const char *File,
277 int Line)
278 {
279 NTSTATUS Status;
280 PVOID Hyperspace;
281 IO_STATUS_BLOCK Iosb;
282 KIRQL OldIrql;
283 PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
284
285 if (!PageBuffer) return STATUS_NO_MEMORY;
286
287 OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
288 Hyperspace = MmCreateHyperspaceMapping(Page);
289 RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE);
290 MmDeleteHyperspaceMapping(Hyperspace);
291 KfLowerIrql(OldIrql);
292
293 DPRINT1("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart, File, Line);
294 Status = MiSimpleWrite
295 (FileObject,
296 FileOffset,
297 PageBuffer,
298 Length,
299 &Iosb);
300
301 ExFreePool(PageBuffer);
302
303 if (!NT_SUCCESS(Status))
304 {
305 DPRINT1("MiSimpleWrite failed (%x)\n", Status);
306 }
307
308 return Status;
309 }