2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
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.
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.
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.
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/cache/section/io.c
21 * PURPOSE: Implements section objects
23 * PROGRAMMERS: Rex Jolliff
36 * Thomas Weidenmueller
37 * Gunnar Andre' Dalsnes
45 /* INCLUDES *****************************************************************/
51 #include <reactos/exeformat.h>
53 #if defined (ALLOC_PRAGMA)
54 #pragma alloc_text(INIT, MmCreatePhysicalMemorySection)
55 #pragma alloc_text(INIT, MmInitSectionImplementation)
58 KEVENT CcpLazyWriteEvent
;
62 MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject
)
64 return IoGetRelatedDeviceObject(FileObject
);
70 This completion function is really required. Paging io completion does almost
71 nothing, including freeing the mdls.
74 _Function_class_(IO_COMPLETION_ROUTINE
)
77 MiSimpleReadComplete(PDEVICE_OBJECT DeviceObject
,
81 PMDL Mdl
= Irp
->MdlAddress
;
83 /* Unlock MDL Pages, page 167. */
84 DPRINT("MiSimpleReadComplete %p\n", Irp
);
87 DPRINT("MDL Unlock %p\n", Mdl
);
92 /* Check if there's an MDL */
93 while ((Mdl
= Irp
->MdlAddress
))
95 /* Clear all of them */
96 Irp
->MdlAddress
= Mdl
->Next
;
100 return STATUS_SUCCESS
;
105 MiSimpleRead is a convenience function that provides either paging or non
106 paging reads. The caching and mm systems use this in paging mode, where
107 a completion function is required as above. The Paging BOOLEAN determines
108 whether the read is issued as a paging read or as an ordinary buffered read.
114 MiSimpleRead(PFILE_OBJECT FileObject
,
115 PLARGE_INTEGER FileOffset
,
119 PIO_STATUS_BLOCK ReadStatus
)
124 PDEVICE_OBJECT DeviceObject
;
125 PIO_STACK_LOCATION IrpSp
;
132 DeviceObject
= MmGetDeviceObjectForFile(FileObject
);
133 ReadStatus
->Status
= STATUS_INTERNAL_ERROR
;
134 ReadStatus
->Information
= 0;
136 ASSERT(DeviceObject
);
138 DPRINT("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %ul\n",
140 &FileObject
->FileName
,
141 FileOffset
->HighPart
,
145 KeInitializeEvent(&ReadWait
, NotificationEvent
, FALSE
);
147 Irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_READ
,
156 return STATUS_NO_MEMORY
;
159 Irp
->Flags
|= (Paging
? IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
| IRP_NOCACHE
: 0) | IRP_SYNCHRONOUS_API
;
161 Irp
->UserEvent
= &ReadWait
;
162 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
163 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
164 IrpSp
= IoGetNextIrpStackLocation(Irp
);
165 IrpSp
->Control
|= SL_INVOKE_ON_SUCCESS
| SL_INVOKE_ON_ERROR
;
166 IrpSp
->FileObject
= FileObject
;
167 IrpSp
->CompletionRoutine
= MiSimpleReadComplete
;
169 /* Non paging case, the FileObject will be dereferenced at completion */
171 ObReferenceObject(FileObject
);
173 Status
= IoCallDriver(DeviceObject
, Irp
);
174 if (Status
== STATUS_PENDING
)
176 DPRINT("KeWaitForSingleObject(&ReadWait)\n");
177 if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait
,
183 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
189 DPRINT("Paging IO Done: %08x\n", ReadStatus
->Status
);
190 /* When "ReadStatus->Information > 0" is false and "ReadStatus->Status == STATUS_END_OF_FILE" is true
191 * it means that read pointer is out of file, so we must fail */
192 Status
= ReadStatus
->Status
== STATUS_END_OF_FILE
&& ReadStatus
->Information
> 0 ? STATUS_SUCCESS
: ReadStatus
->Status
;
198 Convenience function for writing from kernel space. This issues a paging
205 _MiSimpleWrite(PFILE_OBJECT FileObject
,
206 PLARGE_INTEGER FileOffset
,
209 PIO_STATUS_BLOCK ReadStatus
,
216 PDEVICE_OBJECT DeviceObject
;
217 PIO_STACK_LOCATION IrpSp
;
224 DeviceObject
= MmGetDeviceObjectForFile(FileObject
);
225 ASSERT(DeviceObject
);
227 DPRINT("PAGING WRITE: FileObject %p <%wZ> Offset 0x%I64x Length %lu (%s:%d)\n",
229 &FileObject
->FileName
,
230 FileOffset
->QuadPart
,
235 KeInitializeEvent(&ReadWait
, NotificationEvent
, FALSE
);
237 Irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE
,
246 return STATUS_NO_MEMORY
;
249 Irp
->Flags
= IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_API
;
251 Irp
->UserEvent
= &ReadWait
;
252 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
253 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
254 IrpSp
= IoGetNextIrpStackLocation(Irp
);
255 IrpSp
->Control
|= SL_INVOKE_ON_SUCCESS
| SL_INVOKE_ON_ERROR
;
256 IrpSp
->FileObject
= FileObject
;
257 IrpSp
->CompletionRoutine
= MiSimpleReadComplete
;
259 DPRINT("Call Driver\n");
260 Status
= IoCallDriver(DeviceObject
, Irp
);
261 DPRINT("Status %x\n", Status
);
263 if (Status
== STATUS_PENDING
)
265 DPRINT("KeWaitForSingleObject(&ReadWait)\n");
266 if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait
,
272 DPRINT1("Warning: Failed to wait for synchronous IRP\n");
278 DPRINT("Paging IO Done: %08x\n", ReadStatus
->Status
);
279 return ReadStatus
->Status
;
282 extern KEVENT MpwThreadEvent
;
283 FAST_MUTEX MiWriteMutex
;
287 Function which uses MiSimpleWrite to write back a single page to a file.
288 The page in question does not need to be mapped. This function could be
289 made a bit more efficient by avoiding the copy and making a system space
296 _MiWriteBackPage(PFILE_OBJECT FileObject
,
297 PLARGE_INTEGER FileOffset
,
305 IO_STATUS_BLOCK Iosb
;
307 PVOID PageBuffer
= ExAllocatePool(NonPagedPool
, PAGE_SIZE
);
309 if (!PageBuffer
) return STATUS_NO_MEMORY
;
311 Hyperspace
= MiMapPageInHyperSpace(PsGetCurrentProcess(), Page
, &OldIrql
);
314 ExFreePool(PageBuffer
);
315 return STATUS_NO_MEMORY
;
317 RtlCopyMemory(PageBuffer
, Hyperspace
, PAGE_SIZE
);
318 MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Hyperspace
, OldIrql
);
320 DPRINT("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n",
321 &FileObject
->FileName
,
322 FileOffset
->u
.HighPart
,
323 FileOffset
->u
.LowPart
,
327 Status
= MiSimpleWrite(FileObject
,
333 ExFreePool(PageBuffer
);
335 if (!NT_SUCCESS(Status
))
337 DPRINT1("MiSimpleWrite failed (%x)\n", Status
);