]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
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 46520168ab25cd538b71b5e651bdd61b3820fec9..e600d47ce8baa9d3ce9ab612604e240786ef2b7e 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 c2ca4770d81dd14941318b9274dde4bc51808467..324cb8d5859272ac6a055f782b30a31f18dfa888 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 658fbaedd1439a6ec7ca6869c2982cabbf4ec5fb..9957477104fc8d3484f8bc863ad72f090c6b802f 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 6852b1656f3e4e70fb3064aa8d748ac35469244d..b6ab8e6e3096b2bc370649833496f8c42affd5bd 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;
@@ -1740,6 +1775,25 @@ AFSProcessIrpResult( IN PIRP Irp)
             try_return( ntStatus = STATUS_INVALID_PARAMETER);
         }
 
+        //
+        // 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 ae0edfb1b5914e2d56df18e3111abe16232fbdb5..4fd6172493840b44074efb3de0e899f556ce5ce2 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 f83b5fac4a829d7b999a9acf06bc99e7963e2b5a..15115b946d2cbbd6db33bdad8b499b9178e6e2f7 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 841d30267a07ed5514cd22e7cd0f8cba9b3f27f3..4b9eec9e0fec3e435395daf665faca57112f70a4 100644 (file)
@@ -52,6 +52,13 @@ AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
                    IN LARGE_INTEGER StartingByte,
                    IN ULONG ByteCount);
 
+static
+NTSTATUS
+AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
+                         IN PIRP Irp,
+                         IN LARGE_INTEGER StartingByte,
+                         IN ULONG ByteCount);
+
 static
 NTSTATUS
 AFSExtendingWrite( IN AFSFcb *Fcb,
@@ -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:
@@ -1492,6 +1509,177 @@ try_exit:
     return ntStatus;
 }
 
+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,