BOOLEAN bReleaseSectionObject = FALSE;
BOOLEAN bReleasePaging = FALSE;
BOOLEAN bExtendingWrite = FALSE;
+ BOOLEAN bSynchronousFo = FALSE;
BOOLEAN bCompleteIrp = TRUE;
BOOLEAN bForceFlush = FALSE;
BOOLEAN bLockOK;
bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
ulByteCount = pIrpSp->Parameters.Write.Length;
+ bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
}
if( pFcb->ObjectInformation->VolumeCB != NULL &&
- BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.Characteristics, FILE_READ_ONLY_DEVICE))
+ BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
{
AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
if( pFileObject->PrivateCacheMap == NULL)
{
- AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
AFS_TRACE_LEVEL_VERBOSE,
"AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
&pNPFcb->SectionObjectResource,
CcSetDirtyPageThreshold( pFileObject,
AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
}
- __except( EXCEPTION_EXECUTE_HANDLER)
+ __except( EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
ntStatus));
}
- AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
AFS_TRACE_LEVEL_VERBOSE,
"AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
&pNPFcb->SectionObjectResource,
}
}
- if (!CcCanIWrite( pFileObject,
- ulByteCount,
- FALSE,
- bRetry))
- {
-
- AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
- AFS_TRACE_LEVEL_WARNING,
- "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
- pFileObject,
- liStartingByte.QuadPart,
- ulByteCount,
- bRetry ? " RETRY" : ""));
-
- ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
-
- if ( STATUS_PENDING == ntStatus)
- {
-
- bCompleteIrp = FALSE;
- }
- else
- {
-
- AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
- AFS_TRACE_LEVEL_ERROR,
- "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
- pFileObject,
- ntStatus));
- }
-
- try_return( ntStatus);
- }
+ //
+ // On versions of Microsoft Windows older than Vista the IO Manager
+ // will issue multiple outstanding writes on a synchronous file object
+ // if one of the cached writes completes with STATUS_PENDING. This can
+ // result in the writes being completed out of order which can corrupt
+ // the end of file marker. On OS versions older than Vista use a spin
+ // loop instead of deferring the write.
+ //
+
+ if ( bSynchronousFo &&
+ AFSRtlSysVersion.dwMajorVersion < 6)
+ {
+
+ while (!CcCanIWrite( pFileObject,
+ ulByteCount,
+ FALSE,
+ bRetry))
+ {
+ static const LONGLONG llWriteDelay = (LONGLONG)-100000;
+ bRetry = TRUE;
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+ AFS_TRACE_LEVEL_WARNING,
+ "AFSCommonWrite (FO: %p) CcCanIWrite says No room for %u bytes! Retry in 10ms\n",
+ pFileObject,
+ ulByteCount);
+
+ KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
+ }
+ }
+ else
+ {
+
+ if (!CcCanIWrite( pFileObject,
+ ulByteCount,
+ FALSE,
+ bRetry))
+ {
+
+ AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+ AFS_TRACE_LEVEL_WARNING,
+ "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
+ pFileObject,
+ liStartingByte.QuadPart,
+ ulByteCount,
+ bRetry ? " RETRY" : ""));
+
+ ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
+
+ if ( STATUS_PENDING == ntStatus)
+ {
+
+ bCompleteIrp = FALSE;
+ }
+ else
+ {
+
+ AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
+ pFileObject,
+ ntStatus));
+ }
+
+ try_return( ntStatus);
+ }
+ }
}
//
(liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
liStartingByte.HighPart == -1)) ;
- if( bExtendingWrite)
+ if( bExtendingWrite || bNonCachedIo)
{
//
// Check for lock inversion
//
+ //
+ // For bExtendingWrite the PagingResource is needed to protect
+ // the CcSetFileSizes call in AFSExtendingWrite
+ //
+
ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
bReleaseMain = TRUE;
- AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
AFS_TRACE_LEVEL_VERBOSE,
"AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
&pNPFcb->SectionObjectResource,
bReleaseMain = TRUE;
- AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+ AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
AFS_TRACE_LEVEL_VERBOSE,
"AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
&pNPFcb->SectionObjectResource,
if (!bLockOK)
{
+
+ AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSCommonWrite Releasing Fcb SectionObject lock %p SHARED %08lX\n",
+ &pNPFcb->SectionObjectResource,
+ PsGetCurrentThread()));
+
+ AFSReleaseResource( &pNPFcb->SectionObjectResource);
+
+ bReleaseSectionObject = FALSE;
+
AFSReleaseResource( &pNPFcb->Resource);
bReleaseMain = FALSE;
ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
+ //
+ // Fcb->NPFcb->Resource is now held SHARED
+ //
+
if( !NT_SUCCESS(ntStatus))
{
{
//
- // Main and SectionObject resources held Shared
+ // Main resource held Shared
+ // SectionObject resource held exclusive if extending write
//
AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
bRetry ? " RETRY" : ""));
ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
-
}
else
{
- //
- // if bPagingIo, Paging Resource held Shared
- // else Main and SectionObject resources held Shared
- //
-
- if( bReleaseSectionObject)
- {
-
- AFSReleaseResource( &pNPFcb->SectionObjectResource);
-
- bReleaseSectionObject = FALSE;
- }
-
- if( bReleasePaging)
- {
-
- AFSReleaseResource( &pNPFcb->PagingResource);
-
- bReleasePaging = FALSE;
- }
-
- if( bReleaseMain)
- {
-
- AFSReleaseResource( &pNPFcb->Resource);
-
- bReleaseMain = FALSE;
- }
-
AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
"AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
Irp,
ntStatus));
+ if ( NT_SUCCESS( ntStatus) &&
+ ntStatus != STATUS_PENDING)
+ {
+ if ( !bPagingIo)
+ {
+
+ if( bSynchronousFo)
+ {
+
+ pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
+ }
+
+ //
+ // If this extended the VDL, then update it accordingly.
+ // Increasing the VDL does not require a call to CcSetFileSizes.
+ //
+
+ if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
+ {
+
+ pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
+ }
+
+ if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
+ {
+
+ SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
+
+ KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
+ }
+ }
+ }
+
+ if ( ntStatus != STATUS_PENDING &&
+ !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
+ pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
+ bReleaseSectionObject)
+ {
+ //
+ // Regardless of whether or not the a non-paging non-cached write
+ // succeeds or fails, if the file is cached the contents of the
+ // cache are no longer up to date. A CcPurgeCacheSection must be
+ // performed to force subsequent cached reads to obtain the data
+ // from the service.
+ //
+ // The Fcb Resource is dropped in order to permit filters that perform
+ // an open via a worker thread in response to a purge to do so without
+ // deadlocking. The SectionObjectResource is held across the purge to
+ // prevent racing with other cache operations.
+ //
+
+ if( bReleaseMain)
+ {
+
+ AFSReleaseResource( &pNPFcb->Resource);
+
+ bReleaseMain = FALSE;
+ }
+
+ __try
+ {
+
+ if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
+ &liStartingByte,
+ ulByteCount,
+ FALSE))
+ {
+
+ AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+ AFS_TRACE_LEVEL_WARNING,
+ "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+ pFcb->ObjectInformation->FileId.Cell,
+ pFcb->ObjectInformation->FileId.Volume,
+ pFcb->ObjectInformation->FileId.Vnode,
+ pFcb->ObjectInformation->FileId.Unique));
+
+ SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+ }
+ }
+ __except( EXCEPTION_EXECUTE_HANDLER)
+ {
+
+ DWORD ntStatus2 = GetExceptionCode();
+
+ AFSDbgTrace(( 0,
+ 0,
+ "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
+ pFcb->ObjectInformation->FileId.Cell,
+ pFcb->ObjectInformation->FileId.Volume,
+ pFcb->ObjectInformation->FileId.Vnode,
+ pFcb->ObjectInformation->FileId.Unique,
+ ntStatus2));
+
+ SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+ }
+ }
+
ObDereferenceObject(pFileObject);
if( bReleaseSectionObject)
{
+ AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
+ &pNPFcb->SectionObjectResource,
+ PsGetCurrentThread()));
+
AFSReleaseResource( &pNPFcb->SectionObjectResource);
}
ntStatus = Irp->IoStatus.Status;
}
- __except( EXCEPTION_EXECUTE_HANDLER)
+ __except( EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
try_return( ntStatus = STATUS_UNSUCCESSFUL);
}
}
- __except( EXCEPTION_EXECUTE_HANDLER)
+ __except( EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
{
- //
- // We have detected a file we do a write through with.
- //
-
- CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
- &liCurrentOffset,
- ulCurrentIO,
- &iosbFlush);
-
- if( !NT_SUCCESS( iosbFlush.Status))
+ __try
+ {
+ //
+ // We have detected a file we do a write through with.
+ //
+
+ CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
+ &liCurrentOffset,
+ ulCurrentIO,
+ &iosbFlush);
+
+ if( !NT_SUCCESS( iosbFlush.Status))
+ {
+
+ AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
+ Irp,
+ &pFileObject->FileName,
+ pFcb->ObjectInformation->FileId.Cell,
+ pFcb->ObjectInformation->FileId.Volume,
+ pFcb->ObjectInformation->FileId.Vnode,
+ pFcb->ObjectInformation->FileId.Unique,
+ iosbFlush.Status,
+ iosbFlush.Information));
+
+ try_return( ntStatus = iosbFlush.Status);
+ }
+ }
+ __except( EXCEPTION_EXECUTE_HANDLER)
{
+ ntStatus = GetExceptionCode();
+
AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
AFS_TRACE_LEVEL_ERROR,
- "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
+ "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
Irp,
&pFileObject->FileName,
- pFcb->ObjectInformation->FileId.Cell,
- pFcb->ObjectInformation->FileId.Volume,
- pFcb->ObjectInformation->FileId.Vnode,
- pFcb->ObjectInformation->FileId.Unique,
- iosbFlush.Status,
- iosbFlush.Information));
-
- try_return( ntStatus = iosbFlush.Status);
+ liCurrentOffset.QuadPart,
+ ntStatus));
+
+ try_return( ntStatus);
}
}
Irp->IoStatus.Information = ByteCount;
- if( bSynchronousFo)
- {
-
- pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
- }
-
- //
- // If this extended the Vdl, then update it accordingly
- //
-
- if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
- {
-
- pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
- }
-
if ( ForceFlush ||
BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
{
//
pFcb->Specific.File.LastServerFlush.QuadPart = 0;
}
-
- if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
- {
-
- SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
-
- KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
- }
}
AFSCompleteRequest( Irp,
return ntStatus;
}
+//
+// Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
+//
+
static
NTSTATUS
AFSExtendingWrite( IN AFSFcb *Fcb,
//
// If the file is currently cached, then let the MM know about the extension
//
+ // The CcSetFileSizes call should be made with only the PagingResource held
+ // which we are currently not holding.
+ //
if( CcIsFileCached( FileObject))
{