From: Thomas Faber Date: Fri, 1 May 2015 13:20:26 +0000 (+0000) Subject: [NTOS:IO] X-Git-Tag: backups/colins-printing-for-freedom@73041~123 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=e03d4423daa9558d36fbe61c989338ef648280c7 [NTOS:IO] - Implement Fast I/O support in NtReadFile/NtWriteFile CORE-9624 svn path=/trunk/; revision=67494 --- diff --git a/reactos/ntoskrnl/io/iomgr/iofunc.c b/reactos/ntoskrnl/io/iomgr/iofunc.c index a099503feca..ad3958807bf 100644 --- a/reactos/ntoskrnl/io/iomgr/iofunc.c +++ b/reactos/ntoskrnl/io/iomgr/iofunc.c @@ -2255,6 +2255,10 @@ NtReadFile(IN HANDLE FileHandle, 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,13 +2328,16 @@ NtReadFile(IN HANDLE FileHandle, 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))) @@ -2339,6 +2346,61 @@ NtReadFile(IN HANDLE FileHandle, 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 */ Synchronous = TRUE; } @@ -2351,9 +2413,6 @@ NtReadFile(IN HANDLE FileHandle, return STATUS_INVALID_PARAMETER; } - /* Get the device object */ - DeviceObject = IoGetRelatedDeviceObject(FileObject); - /* Clear the File Object's event */ KeClearEvent(&FileObject->Event); @@ -3150,6 +3209,10 @@ NtWriteFile(IN HANDLE FileHandle, 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,13 +3307,16 @@ NtWriteFile(IN HANDLE FileHandle, 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))) @@ -3259,6 +3325,59 @@ NtWriteFile(IN HANDLE FileHandle, 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 */ Synchronous = TRUE; } @@ -3271,9 +3390,6 @@ NtWriteFile(IN HANDLE FileHandle, return STATUS_INVALID_PARAMETER; } - /* Get the device object */ - DeviceObject = IoGetRelatedDeviceObject(FileObject); - /* Clear the File Object's event */ KeClearEvent(&FileObject->Event);