/*
* Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
- * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
BOOLEAN bReleasePaging = FALSE;
BOOLEAN bExtendingWrite = FALSE;
BOOLEAN bSynchronousFo = FALSE;
+ BOOLEAN bWriteToEndOfFile = FALSE;
+ BOOLEAN bWait = FALSE;
BOOLEAN bCompleteIrp = TRUE;
BOOLEAN bForceFlush = FALSE;
BOOLEAN bLockOK;
liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
+ bWait = IoIsOperationSynchronous( Irp);
ulByteCount = pIrpSp->Parameters.Write.Length;
bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
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" : ""));
+ //
+ // 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)
+ {
- ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
+ while (!CcCanIWrite( pFileObject,
+ ulByteCount,
+ bWait && !bRetry,
+ bRetry))
+ {
+ static const LONGLONG llWriteDelay = (LONGLONG)-100000;
+ bRetry = TRUE;
- if ( STATUS_PENDING == ntStatus)
- {
+ 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);
- bCompleteIrp = FALSE;
- }
- else
- {
+ KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
+ }
+ }
+ else
+ {
- AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
- AFS_TRACE_LEVEL_ERROR,
- "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
- pFileObject,
- ntStatus));
- }
+ if (!CcCanIWrite( pFileObject,
+ ulByteCount,
+ bWait && !bRetry,
+ bRetry))
+ {
- try_return( ntStatus);
- }
+ 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);
+ }
+ }
}
//
else
{
- bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
- pFcb->Header.FileSize.QuadPart) ||
- (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
- liStartingByte.HighPart == -1)) ;
+ bWriteToEndOfFile = liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
+ liStartingByte.HighPart == -1;
+
+ bExtendingWrite = ( bWriteToEndOfFile ||
+ ((liStartingByte.QuadPart + ulByteCount) >=
+ pFcb->Header.FileSize.QuadPart));
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,
bReleaseSectionObject = TRUE;
- if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
- liStartingByte.HighPart == -1)
+ if ( bWriteToEndOfFile)
{
if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
{
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;
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,
Irp,
ntStatus));
- if ( NT_SUCCESS( ntStatus))
+ if ( NT_SUCCESS( ntStatus) &&
+ ntStatus != STATUS_PENDING)
{
if ( !bPagingIo)
{
- if( bSynchronousFo)
+ if( bSynchronousFo)
{
pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
}
}
- if ( !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
+ if ( ntStatus != STATUS_PENDING &&
+ !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
bReleaseSectionObject)
{
AFSDbgTrace(( 0,
0,
- "EXCEPTION - AFSProcessOverwriteSupercede MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
+ "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,
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);
}
}
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))
{
__Enter
{
- pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
-
pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
}
+ pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
+
AFSAcquireShared( &pFcb->NPFcb->Resource,
TRUE);