Windows: Direct IO for AFS Redirector
authorPeter Scott <pscott@kerneldrivers.com>
Fri, 25 Jan 2013 05:46:37 +0000 (00:46 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Sat, 23 Feb 2013 08:21:48 +0000 (00:21 -0800)
Implement a new IO processing model in which extents are not passed between
afsredirlib.sys and afsd_service.exe.  Instead the AFSCache file is
maintained exclusively by the service and the redirector locks kernel
memory, maps it into the service's address space, and permits the service
to manage all IO directly.

This interface adds an AFS Cache Bypass option to the AFS Redirector which
is activated when the file handle has been opened with the no intermediate
buffering option.

This patchset implements the kernel interface.  A subsequent
patchset will implement the service component.

Assisted by Jeffrey Altman <jaltman@your-file-system.com>

Change-Id: I25a4764db060b3b3f2b0de4006479dd3a220c6eb
Reviewed-on: http://gerrit.openafs.org/9210
Reviewed-by: Peter Scott <pscott@kerneldrivers.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/common/AFSRedirCommonDefines.h
src/WINNT/afsrdr/common/AFSUserDefines.h
src/WINNT/afsrdr/common/AFSUserStructs.h
src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp
src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp
src/WINNT/afsrdr/kernel/lib/AFSRead.cpp
src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp

index 4652016..e600d47 100644 (file)
@@ -247,6 +247,7 @@ static inline void AFSBreakPoint() {
 #define AFS_DEVICE_FLAG_HIDE_DOT_NAMES          0x00000001
 #define AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN     0x00000002
 #define AFS_DEVICE_FLAG_DISABLE_SHORTNAMES      0x00000004
+#define AFS_DEVICE_FLAG_DIRECT_SERVICE_IO       0x00000008
 
 #endif
 
index c2ca477..324cb8d 100644 (file)
@@ -92,6 +92,8 @@
 #define AFS_REQUEST_TYPE_RELEASE_FILE_ACCESS     0x00000021
 #define AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO    0x00000022
 #define AFS_REQUEST_TYPE_HARDLINK_FILE           0x00000023
+#define AFS_REQUEST_TYPE_PROCESS_READ_FILE       0x00000024
+#define AFS_REQUEST_TYPE_PROCESS_WRITE_FILE      0x00000025
 
 //
 // Request Flags, these are passed up from the file system
 #define AFS_REQUEST_LOCAL_SYSTEM_PAG             0x00000200 // Indicates that the caller is or was at some point a system
                                                             // process
 
+#define AFS_REQUEST_FLAG_CACHE_BYPASS            0x00000400 // Indicates that the AFS_REQUEST_TYPE_PROCESS_READ_FILE or
+                                                            // AFS_REQUEST_TYPE_PROCESS_WRITE_FILE is to be performed directly
+                                                            // against the file server bypassing the AFS Cache file.
+
 #define AFS_REQUEST_FLAG_LAST_COMPONENT          0x00000800 // During an AFS_REQUEST_TYPE_TARGET_BY_NAME the provided name
                                                             // is the last component in the path.
 
index 658fbae..9957477 100644 (file)
@@ -110,6 +110,7 @@ typedef struct _AFS_COMM_RESULT_BLOCK
 #define AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES          0x00000001
 #define AFS_REDIR_INIT_NO_PAGING_FILE               0x00000002
 #define AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES     0x00000004
+#define AFS_REDIR_INIT_PERFORM_SERVICE_IO           0x00000008
 
 typedef struct _AFS_REDIR_INIT_INFO_CB
 {
@@ -1243,5 +1244,45 @@ typedef struct _AFS_REPARSE_TAG_INFORMATION
 
 } AFSReparseTagInfo;
 
+//
+// File IO CB
+//
+
+typedef struct _AFS_FILE_IO_CB
+{
+
+    LARGE_INTEGER   IOOffset;
+
+    ULONG           IOLength;
+
+    void           *MappedIOBuffer; // Mapped buffer for access by service
+
+    void           *SystemIOBuffer; // Service should not access this pointer
+
+    void           *SystemIOBufferMdl; // The service should not access this pointer
+
+    LARGE_INTEGER   LastAccessTime;
+
+    LARGE_INTEGER   LastWriteTime;
+
+    LARGE_INTEGER   ChangeTime;
+
+    LARGE_INTEGER   CreateTime;
+
+    LARGE_INTEGER   EndOfFile;
+
+} AFSFileIOCB;
+
+typedef struct _AFS_FILE_IO_RESULT_CB
+{
+
+    ULONG           Length;
+
+    LARGE_INTEGER   DataVersion;
+
+    LARGE_INTEGER   Expiration;                /* FILETIME */
+
+} AFSFileIOResultCB;
+
 #endif /* _AFS_USER_STRUCT_H */
 
index 6852b16..b6ab8e6 100644 (file)
@@ -1174,6 +1174,21 @@ AFSCleanupIrpPool()
 
             pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
 
+            if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
+                pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
+            {
+
+                AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
+
+                if( pFileIO->MappedIOBuffer != NULL)
+                {
+                    MmUnmapLockedPages( pFileIO->MappedIOBuffer,
+                                        (PMDL)pFileIO->SystemIOBufferMdl);
+
+                    pFileIO->MappedIOBuffer = NULL;
+                }
+            }
+
             //
             // Here we will set the event of the requestor and let the blocked thread
             // free the data block
@@ -1550,6 +1565,26 @@ AFSProcessIrpRequest( IN PIRP Irp)
                                    pRequest->NameLength);
                 }
 
+                //
+                // If this is an IO request then need to map the system buffer to the service process
+                //
+
+                if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
+                    pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
+                {
+
+                    AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
+
+                    ASSERT( pFileIO->SystemIOBuffer != NULL);
+
+                    pFileIO->MappedIOBuffer = MmMapLockedPagesSpecifyCache( (PMDL)pFileIO->SystemIOBufferMdl,
+                                                                            UserMode,
+                                                                            MmCached,
+                                                                            NULL,
+                                                                            FALSE,
+                                                                            NormalPagePriority);
+                }
+
                 pRequest->DataOffset = 0;
 
                 pRequest->DataLength = pEntry->DataLength;
@@ -1741,6 +1776,25 @@ AFSProcessIrpResult( IN PIRP Irp)
         }
 
         //
+        // If this is an IO request, unmap the user buffer
+        //
+
+        if( pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
+            pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
+        {
+
+            AFSFileIOCB *pFileIO = (AFSFileIOCB *)pCurrentEntry->Data;
+
+            if( pFileIO->MappedIOBuffer != NULL)
+            {
+                MmUnmapLockedPages( pFileIO->MappedIOBuffer,
+                                    (PMDL)pFileIO->SystemIOBufferMdl);
+
+                pFileIO->MappedIOBuffer = NULL;
+            }
+        }
+
+        //
         // OK, move in the result information
         //
 
index ae0edfb..4fd6172 100644 (file)
@@ -510,155 +510,172 @@ AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo)
             SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES);
         }
 
-        if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
-            RedirInitInfo->MemoryCacheLength.QuadPart != 0)
+        //
+        // Are we performing direct to service IO?
+        //
+
+        if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_PERFORM_SERVICE_IO))
         {
 
-            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+            //
+            // Send IO requests directly to service
+            //
 
-#ifdef AMD64
-            pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
-                                                          (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
-                                                          RedirInitInfo->MemoryCacheLength.QuadPart);
-#else
-            pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
-                                                          (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
-                                                          RedirInitInfo->MemoryCacheLength.LowPart);
-#endif
+            SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO);
+        }
+        else
+        {
 
-            if( pDevExt->Specific.RDR.CacheMdl != NULL)
+            if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
+                RedirInitInfo->MemoryCacheLength.QuadPart != 0)
             {
 
-                __try
-                {
+                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
 
-                    MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
-                                         KernelMode,
-                                         IoModifyAccess);
+#ifdef AMD64
+                pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
+                                                              (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
+                                                              RedirInitInfo->MemoryCacheLength.QuadPart);
+#else
+                pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
+                                                              (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
+                                                              RedirInitInfo->MemoryCacheLength.LowPart);
+#endif
 
-                    pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
-                                                                                           NormalPagePriority);
-                }
-                __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
+                if( pDevExt->Specific.RDR.CacheMdl != NULL)
                 {
 
-                    AFSDumpTraceFilesFnc();
-
-                    IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
-                    pDevExt->Specific.RDR.CacheMdl = NULL;
-                }
+                    __try
+                    {
 
-                if( pDevExt->Specific.RDR.CacheMdl != NULL)
-                {
-                    pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
-                    ntStatus = STATUS_SUCCESS;
-                }
+                        MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
+                                             KernelMode,
+                                             IoModifyAccess);
 
-            }
-        }
+                        pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
+                                                                                               NormalPagePriority);
+                    }
+                    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
+                    {
 
-        if( !NT_SUCCESS( ntStatus) &&
-            RedirInitInfo->CacheFileNameLength == 0)
-        {
+                        AFSDumpTraceFilesFnc();
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
-                          AFS_TRACE_LEVEL_ERROR,
-                          "AFSInitializeRedirector Unable to initialize cache file %08lX\n",
-                          ntStatus);
+                        IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
+                        pDevExt->Specific.RDR.CacheMdl = NULL;
+                    }
 
-            try_return( ntStatus);
-        }
+                    if( pDevExt->Specific.RDR.CacheMdl != NULL)
+                    {
+                        pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
+                        ntStatus = STATUS_SUCCESS;
+                    }
 
-        if( pDevExt->Specific.RDR.CacheMdl == NULL)
-        {
+                }
+            }
 
-            if( RedirInitInfo->CacheFileNameLength == 0)
+            if( !NT_SUCCESS( ntStatus) &&
+                RedirInitInfo->CacheFileNameLength == 0)
             {
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
                               AFS_TRACE_LEVEL_ERROR,
-                              "AFSInitializeRedirector CacheMdl == NULL\n");
+                              "AFSInitializeRedirector Unable to initialize cache file %08lX\n",
+                              ntStatus);
 
-                try_return( ntStatus = STATUS_INVALID_PARAMETER);
+                try_return( ntStatus);
             }
 
-            //
-            // Go open the cache file
-            //
+            if( pDevExt->Specific.RDR.CacheMdl == NULL)
+            {
 
-            pDevExt->Specific.RDR.CacheFile.Length = 0;
-            pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR));
+                if( RedirInitInfo->CacheFileNameLength == 0)
+                {
 
-            pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
-                                                                                        pDevExt->Specific.RDR.CacheFile.MaximumLength,
-                                                                                        AFS_GENERIC_MEMORY_24_TAG);
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSInitializeRedirector CacheMdl == NULL\n");
 
-            if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL)
-            {
+                    try_return( ntStatus = STATUS_INVALID_PARAMETER);
+                }
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n");
+                //
+                // Go open the cache file
+                //
 
-                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-            }
+                pDevExt->Specific.RDR.CacheFile.Length = 0;
+                pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR));
 
-            RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer,
-                           L"\\??\\",
-                           4 * sizeof( WCHAR));
+                pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                                            pDevExt->Specific.RDR.CacheFile.MaximumLength,
+                                                                                            AFS_GENERIC_MEMORY_24_TAG);
 
-            pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR);
+                if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL)
+                {
 
-            RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)],
-                           RedirInitInfo->CacheFileName,
-                           RedirInitInfo->CacheFileNameLength);
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n");
 
-            pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength;
+                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+                }
 
-            InitializeObjectAttributes( &stObjectAttribs,
-                                        &pDevExt->Specific.RDR.CacheFile,
-                                        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
-                                        NULL,
-                                        NULL);
+                RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer,
+                               L"\\??\\",
+                               4 * sizeof( WCHAR));
 
-            ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle,
-                                   GENERIC_READ | GENERIC_WRITE,
-                                   &stObjectAttribs,
-                                   &stIoStatus,
-                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                   FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS);
+                pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR);
 
-            if( !NT_SUCCESS( ntStatus))
-            {
+                RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)],
+                               RedirInitInfo->CacheFileName,
+                               RedirInitInfo->CacheFileNameLength);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSInitializeRedirector ZwOpenFile failure %08lX\n",
-                              ntStatus);
+                pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength;
 
-                try_return( ntStatus);
-            }
+                InitializeObjectAttributes( &stObjectAttribs,
+                                            &pDevExt->Specific.RDR.CacheFile,
+                                            OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+                                            NULL,
+                                            NULL);
 
-            //
-            // Map to the fileobject
-            //
+                ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle,
+                                       GENERIC_READ | GENERIC_WRITE,
+                                       &stObjectAttribs,
+                                       &stIoStatus,
+                                       FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                       FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS);
 
-            ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle,
-                                                  SYNCHRONIZE,
-                                                  NULL,
-                                                  KernelMode,
-                                                  (void **)&pDevExt->Specific.RDR.CacheFileObject,
-                                                  NULL);
+                if( !NT_SUCCESS( ntStatus))
+                {
 
-            if( !NT_SUCCESS( ntStatus))
-            {
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSInitializeRedirector ZwOpenFile failure %08lX\n",
+                                  ntStatus);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n",
-                              ntStatus);
+                    try_return( ntStatus);
+                }
 
-                try_return( ntStatus);
+                //
+                // Map to the fileobject
+                //
+
+                ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle,
+                                                      SYNCHRONIZE,
+                                                      NULL,
+                                                      KernelMode,
+                                                      (void **)&pDevExt->Specific.RDR.CacheFileObject,
+                                                      NULL);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n",
+                                  ntStatus);
+
+                    try_return( ntStatus);
+                }
             }
         }
 
index f83b5fa..15115b9 100644 (file)
@@ -757,6 +757,168 @@ try_exit:
     return ntStatus;
 }
 
+static
+NTSTATUS
+AFSNonCachedReadDirect( IN PDEVICE_OBJECT DeviceObject,
+                        IN PIRP Irp,
+                        IN LARGE_INTEGER StartingByte)
+{
+    NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
+    AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
+    AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
+    VOID              *pSystemBuffer = NULL;
+    ULONG              ulByteCount = 0;
+    ULONG              ulReadByteCount = 0;
+    ULONG              ulFlags;
+    BOOLEAN            bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
+    AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+    AFSFileIOCB        stFileIORequest;
+    AFSFileIOResultCB  stFileIOResult;
+    ULONG              ulResultLen = 0;
+
+    __Enter
+    {
+
+        Irp->IoStatus.Information = 0;
+
+        ulByteCount = pIrpSp->Parameters.Read.Length;
+
+        if (ulByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNonCachedReadDirect (%p) Request larger than MaxIO %I64X\n",
+                          Irp,
+                          pDevExt->Specific.RDR.MaxIo.QuadPart);
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        pSystemBuffer = AFSLockSystemBuffer( Irp,
+                                             ulByteCount);
+
+        if( pSystemBuffer == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNonCachedReadDirect (%p) Failed to map system buffer\n",
+                          Irp);
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        if( StartingByte.QuadPart + ulByteCount > pFcb->Header.FileSize.QuadPart)
+        {
+            ULONG zeroCount = (ULONG) (StartingByte.QuadPart + ulByteCount - pFcb->Header.FileSize.QuadPart);
+            ulReadByteCount = (ULONG)(pFcb->Header.FileSize.QuadPart - StartingByte.QuadPart);
+
+            //
+            // Clear up to EOF
+            //
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSNonCachedReadDirect (%p) Zeroing to EOF zero byte length %08lX\n",
+                          Irp,
+                          zeroCount);
+
+            RtlZeroMemory( ((PCHAR)pSystemBuffer) + ulReadByteCount, zeroCount);
+        }
+        else
+        {
+            ulReadByteCount = ulByteCount;
+        }
+
+        //
+        // Issue the request at the service for processing
+        //
+
+        ulResultLen = sizeof( AFSFileIOResultCB);
+
+        RtlZeroMemory( &stFileIORequest,
+                       sizeof( AFSFileIOCB));
+
+        RtlZeroMemory( &stFileIOResult,
+                       sizeof( AFSFileIOResultCB));
+
+        stFileIORequest.SystemIOBuffer = pSystemBuffer;
+
+        stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
+
+        stFileIORequest.IOOffset = StartingByte;
+
+        stFileIORequest.IOLength = ulReadByteCount;
+
+        ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+
+        if ( bNoIntermediateBuffering)
+        {
+
+            ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
+        }
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_READ_FILE,
+                                      ulFlags,
+                                      &pCcb->AuthGroup,
+                                      &pCcb->DirectoryCB->NameInformation.FileName,
+                                      &pFcb->ObjectInformation->FileId,
+                                      pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
+                                      pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
+                                      &stFileIORequest,
+                                      sizeof( AFSFileIOCB),
+                                      &stFileIOResult,
+                                      &ulResultLen);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
+        }
+        else
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNonCachedReadDirect (%p) Failed to send read to service Status %08lX\n",
+                          Irp,
+                          ntStatus);
+        }
+
+try_exit:
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSNonCachedReadDirect (%p) Completed request Status %08lX\n",
+                      Irp,
+                      ntStatus);
+
+        if (NT_SUCCESS(ntStatus) &&
+            !BooleanFlagOn( Irp->Flags, IRP_PAGING_IO) &&
+            BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO))
+        {
+            //
+            // Update the CBO if this is a sync, nopaging read
+            //
+            pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ulByteCount;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSNonCachedReadDirect Completing irp %08lX Status %08lX Info %08lX\n",
+                      Irp,
+                      ntStatus,
+                      Irp->IoStatus.Information);
+
+        AFSCompleteRequest( Irp, ntStatus );
+    }
+
+    return ntStatus;
+}
+
 //
 // Function: AFSDispatch
 //
@@ -825,6 +987,7 @@ AFSCommonRead( IN PDEVICE_OBJECT DeviceObject,
     PFILE_OBJECT        pFileObject = NULL;
     LARGE_INTEGER       liStartingByte;
     ULONG               ulByteCount;
+    AFSDeviceExt       *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
 
     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
     pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
@@ -937,6 +1100,7 @@ AFSCommonRead( IN PDEVICE_OBJECT DeviceObject,
         // No fileobject yet?  Bail.
         //
         if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
+            !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
             NULL == pDeviceExt->Specific.RDR.CacheFileObject)
         {
 
@@ -1282,7 +1446,15 @@ AFSCommonRead( IN PDEVICE_OBJECT DeviceObject,
                           liStartingByte.QuadPart,
                           ulByteCount);
 
-            ntStatus = AFSNonCachedRead( DeviceObject, Irp,  liStartingByte);
+            if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
+            {
+
+                ntStatus = AFSNonCachedReadDirect( DeviceObject, Irp,  liStartingByte);
+            }
+            else
+            {
+                ntStatus = AFSNonCachedRead( DeviceObject, Irp,  liStartingByte);
+            }
         }
 
 try_exit:
index 841d302..4b9eec9 100644 (file)
@@ -54,6 +54,13 @@ AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
 
 static
 NTSTATUS
+AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
+                         IN PIRP Irp,
+                         IN LARGE_INTEGER StartingByte,
+                         IN ULONG ByteCount);
+
+static
+NTSTATUS
 AFSExtendingWrite( IN AFSFcb *Fcb,
                    IN PFILE_OBJECT FileObject,
                    IN LONGLONG NewLength);
@@ -117,6 +124,7 @@ AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
     BOOLEAN            bLockOK;
     HANDLE             hCallingUser = OnBehalfOf;
     ULONGLONG          ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
+    AFSDeviceExt       *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
 
     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
 
@@ -225,6 +233,7 @@ AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
         // Is the Cache not there yet?  Exit.
         //
         if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
+            !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
             NULL == pDeviceExt->Specific.RDR.CacheFileObject)
         {
 
@@ -695,7 +704,15 @@ AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
                           ulByteCount,
                           bRetry ? " RETRY" : "");
 
-            ntStatus = AFSNonCachedWrite( DeviceObject, Irp,  liStartingByte, ulByteCount);
+            if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
+            {
+
+                ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp,  liStartingByte, ulByteCount);
+            }
+            else
+            {
+                ntStatus = AFSNonCachedWrite( DeviceObject, Irp,  liStartingByte, ulByteCount);
+            }
         }
 
 try_exit:
@@ -1494,6 +1511,177 @@ try_exit:
 
 static
 NTSTATUS
+AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
+                         IN PIRP Irp,
+                         IN LARGE_INTEGER StartingByte,
+                         IN ULONG ByteCount)
+{
+    NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
+    VOID              *pSystemBuffer = NULL;
+    BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
+    AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
+    AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
+    BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
+    BOOLEAN            bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
+    AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+    AFSFileIOCB        stFileIORequest;
+    AFSFileIOResultCB  stFileIOResult;
+    ULONG              ulResultLen = 0;
+    ULONG              ulFlags;
+
+    __Enter
+    {
+        Irp->IoStatus.Information = 0;
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
+                      pFileObject,
+                      StartingByte.HighPart,
+                      StartingByte.LowPart,
+                      ByteCount);
+
+        if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
+                          Irp,
+                          ByteCount,
+                          pIrpSp->Parameters.Write.Length,
+                          pDevExt->Specific.RDR.MaxIo.QuadPart);
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        //
+        // Get the mapping for the buffer
+        //
+        pSystemBuffer = AFSLockSystemBuffer( Irp,
+                                             ByteCount);
+
+        if( pSystemBuffer == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
+                          Irp);
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Issue the request at the service for processing
+        //
+
+        ulResultLen = sizeof( AFSFileIOResultCB);
+
+        RtlZeroMemory( &stFileIORequest,
+                       sizeof( AFSFileIOCB));
+
+        RtlZeroMemory( &stFileIOResult,
+                       sizeof( AFSFileIOResultCB));
+
+        stFileIORequest.SystemIOBuffer = pSystemBuffer;
+
+        stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
+
+        stFileIORequest.IOLength = ByteCount;
+
+        stFileIORequest.IOOffset = StartingByte;
+
+        ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+
+        if ( bNoIntermediateBuffering)
+        {
+
+            ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
+        }
+
+        //
+        // Update file metadata
+        //
+
+        stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
+
+        stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
+
+        stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
+
+        stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
+
+        stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
+
+        //
+        // Write the data to the service
+        //
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
+                                      ulFlags,
+                                      &pCcb->AuthGroup,
+                                      &pCcb->DirectoryCB->NameInformation.FileName,
+                                      &pFcb->ObjectInformation->FileId,
+                                      pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
+                                      pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
+                                      &stFileIORequest,
+                                      sizeof( AFSFileIOCB),
+                                      &stFileIOResult,
+                                      &ulResultLen);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
+        }
+        else
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
+                          Irp,
+                          ntStatus);
+
+        }
+
+try_exit:
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
+                      pFileObject,
+                      StartingByte.HighPart,
+                      StartingByte.LowPart,
+                      ByteCount,
+                      ntStatus);
+
+        if (NT_SUCCESS(ntStatus) &&
+            !bPagingIo &&
+            bSynchronousFo)
+        {
+
+            pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
+                      Irp,
+                      ntStatus,
+                      Irp->IoStatus.Information);
+
+        AFSCompleteRequest( Irp, ntStatus);
+    }
+
+    return ntStatus;
+}
+
+static
+NTSTATUS
 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
                 IN PIRP Irp,
                 IN LARGE_INTEGER StartingByte,