From: Peter Scott Date: Fri, 25 Jan 2013 05:46:37 +0000 (-0500) Subject: Windows: Direct IO for AFS Redirector X-Git-Tag: openafs-stable-1_8_0pre1~1481 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=be0296a8ade48c8944056999eab787bc0db1a01f Windows: Direct IO for AFS Redirector 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 Change-Id: I25a4764db060b3b3f2b0de4006479dd3a220c6eb Reviewed-on: http://gerrit.openafs.org/9210 Reviewed-by: Peter Scott Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- diff --git a/src/WINNT/afsrdr/common/AFSRedirCommonDefines.h b/src/WINNT/afsrdr/common/AFSRedirCommonDefines.h index 4652016..e600d47 100644 --- a/src/WINNT/afsrdr/common/AFSRedirCommonDefines.h +++ b/src/WINNT/afsrdr/common/AFSRedirCommonDefines.h @@ -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 diff --git a/src/WINNT/afsrdr/common/AFSUserDefines.h b/src/WINNT/afsrdr/common/AFSUserDefines.h index c2ca477..324cb8d 100644 --- a/src/WINNT/afsrdr/common/AFSUserDefines.h +++ b/src/WINNT/afsrdr/common/AFSUserDefines.h @@ -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 @@ -143,6 +145,10 @@ #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. diff --git a/src/WINNT/afsrdr/common/AFSUserStructs.h b/src/WINNT/afsrdr/common/AFSUserStructs.h index 658fbae..9957477 100644 --- a/src/WINNT/afsrdr/common/AFSUserStructs.h +++ b/src/WINNT/afsrdr/common/AFSUserStructs.h @@ -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 */ diff --git a/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp index 6852b16..b6ab8e6 100644 --- a/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp +++ b/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp @@ -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 // diff --git a/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp index ae0edfb..4fd6172 100644 --- a/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp +++ b/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp @@ -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); + } } } diff --git a/src/WINNT/afsrdr/kernel/lib/AFSRead.cpp b/src/WINNT/afsrdr/kernel/lib/AFSRead.cpp index f83b5fa..15115b9 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSRead.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSRead.cpp @@ -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: diff --git a/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp b/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp index 841d302..4b9eec9 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp @@ -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,