Author: tfaber
Date: Fri May 1 13:20:26 2015
New Revision: 67494
URL:
http://svn.reactos.org/svn/reactos?rev=67494&view=rev
Log:
[NTOS:IO]
- Implement Fast I/O support in NtReadFile/NtWriteFile
CORE-9624
Modified:
trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c [iso-8859-1] Fri May 1 13:20:26 2015
@@ -2255,6 +2255,10 @@
ULONG CapturedKey = 0;
BOOLEAN Synchronous = FALSE;
PMDL Mdl;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ IO_STATUS_BLOCK KernelIosb;
+ BOOLEAN Success;
+
PAGED_CODE();
CapturedByteOffset.QuadPart = 0;
IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
@@ -2324,19 +2328,77 @@
KeClearEvent(EventObject);
}
+ /* Get the device object */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+
/* Check if we should use Sync IO or not */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Lock the file object */
IopLockFileObject(FileObject);
- /* Check if we don't have a byte offset avilable */
+ /* Check if we don't have a byte offset available */
if (!(ByteOffset) ||
((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) &&
(CapturedByteOffset.u.HighPart == -1)))
{
/* Use the Current Byte Offset instead */
CapturedByteOffset = FileObject->CurrentByteOffset;
+ }
+
+ /* If the file is cached, try fast I/O */
+ if (FileObject->PrivateCacheMap)
+ {
+ /* Perform fast write */
+ FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
+ Success = FastIoDispatch->FastIoRead(FileObject,
+ &CapturedByteOffset,
+ Length,
+ TRUE,
+ CapturedKey,
+ Buffer,
+ &KernelIosb,
+ DeviceObject);
+
+ /* Only accept the result if we got a straightforward status */
+ if (Success &&
+ (KernelIosb.Status == STATUS_SUCCESS ||
+ KernelIosb.Status == STATUS_BUFFER_OVERFLOW ||
+ KernelIosb.Status == STATUS_END_OF_FILE))
+ {
+ /* Fast path -- update transfer & operation counts */
+ IopUpdateOperationCount(IopReadTransfer);
+ IopUpdateTransferCount(IopReadTransfer,
+ (ULONG)KernelIosb.Information);
+
+ /* Enter SEH to write the IOSB back */
+ _SEH2_TRY
+ {
+ /* Write it back to the caller */
+ *IoStatusBlock = KernelIosb;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* The caller's IOSB was invalid, so fail */
+ if (EventObject) ObDereferenceObject(EventObject);
+ IopUnlockFileObject(FileObject);
+ ObDereferenceObject(FileObject);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ /* Signal the completion event */
+ if (EventObject)
+ {
+ KeSetEvent(EventObject, 0, FALSE);
+ ObDereferenceObject(EventObject);
+ }
+
+ /* Clean up */
+ IopUnlockFileObject(FileObject);
+ ObDereferenceObject(FileObject);
+ return KernelIosb.Status;
+ }
}
/* Remember we are sync */
@@ -2350,9 +2412,6 @@
ObDereferenceObject(FileObject);
return STATUS_INVALID_PARAMETER;
}
-
- /* Get the device object */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
/* Clear the File Object's event */
KeClearEvent(&FileObject->Event);
@@ -3150,6 +3209,10 @@
BOOLEAN Synchronous = FALSE;
PMDL Mdl;
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ IO_STATUS_BLOCK KernelIosb;
+ BOOLEAN Success;
+
PAGED_CODE();
CapturedByteOffset.QuadPart = 0;
IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
@@ -3244,19 +3307,75 @@
KeClearEvent(EventObject);
}
+ /* Get the device object */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+
/* Check if we should use Sync IO or not */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Lock the file object */
IopLockFileObject(FileObject);
- /* Check if we don't have a byte offset avilable */
+ /* Check if we don't have a byte offset available */
if (!(ByteOffset) ||
((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) &&
(CapturedByteOffset.u.HighPart == -1)))
{
/* Use the Current Byte Offset instead */
CapturedByteOffset = FileObject->CurrentByteOffset;
+ }
+
+ /* If the file is cached, try fast I/O */
+ if (FileObject->PrivateCacheMap)
+ {
+ /* Perform fast read */
+ FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
+ Success = FastIoDispatch->FastIoWrite(FileObject,
+ &CapturedByteOffset,
+ Length,
+ TRUE,
+ CapturedKey,
+ Buffer,
+ &KernelIosb,
+ DeviceObject);
+
+ /* Only accept the result if it was successful */
+ if (Success &&
+ KernelIosb.Status == STATUS_SUCCESS)
+ {
+ /* Fast path -- update transfer & operation counts */
+ IopUpdateOperationCount(IopWriteTransfer);
+ IopUpdateTransferCount(IopWriteTransfer,
+ (ULONG)KernelIosb.Information);
+
+ /* Enter SEH to write the IOSB back */
+ _SEH2_TRY
+ {
+ /* Write it back to the caller */
+ *IoStatusBlock = KernelIosb;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* The caller's IOSB was invalid, so fail */
+ if (EventObject) ObDereferenceObject(EventObject);
+ IopUnlockFileObject(FileObject);
+ ObDereferenceObject(FileObject);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ /* Signal the completion event */
+ if (EventObject)
+ {
+ KeSetEvent(EventObject, 0, FALSE);
+ ObDereferenceObject(EventObject);
+ }
+
+ /* Clean up */
+ IopUnlockFileObject(FileObject);
+ ObDereferenceObject(FileObject);
+ return KernelIosb.Status;
+ }
}
/* Remember we are sync */
@@ -3270,9 +3389,6 @@
ObDereferenceObject(FileObject);
return STATUS_INVALID_PARAMETER;
}
-
- /* Get the device object */
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
/* Clear the File Object's event */
KeClearEvent(&FileObject->Event);