[NTOS:IO]
authorThomas Faber <thomas.faber@reactos.org>
Fri, 1 May 2015 13:20:26 +0000 (13:20 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Fri, 1 May 2015 13:20:26 +0000 (13:20 +0000)
- Implement Fast I/O support in NtReadFile/NtWriteFile
CORE-9624

svn path=/trunk/; revision=67494

reactos/ntoskrnl/io/iomgr/iofunc.c

index a099503..ad39588 100644 (file)
@@ -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);