From: Jeffrey Altman Date: Tue, 9 Apr 2013 14:35:52 +0000 (-0400) Subject: Windows: CcPurge range modified by non-cached write X-Git-Tag: upstream/1.8.0_pre1^2~1222 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=aa0046a7220d8b21f2694d7f9534d7383422731b;p=packages%2Fo%2Fopenafs.git Windows: CcPurge range modified by non-cached write When a non-cached non-paging write occurs, the update bypasses the Windows cache. As a result any cached data in the modified range is now invalid and must be purged. CcPurgeCacheSection is known to trigger some filter drivers to open the file from a worker thread. To avoid a deadlock on the Fcb->NPFcb->Resource that resource must be dropped. Holding the SectionObjectResource exclusive is sufficient to protect against races with other writes, reads and SetEndOfFile operations. While purging the cache prior to calling the service might be more desireable, it cannot be done safely without violating the lock hierarchy. Therefore, the purge is performed after any call to the service completes. Change-Id: I953a74a0675875eb6be85f85ce924473deb3347f Reviewed-on: http://gerrit.openafs.org/9756 Tested-by: BuildBot Reviewed-by: Rod Widdowson Reviewed-by: Peter Scott Reviewed-by: Jeffrey Altman --- diff --git a/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp b/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp index dbe4f758f..744ef0aa0 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp @@ -728,6 +728,49 @@ try_exit: } } + if ( !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; + } + + 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); + } + } + ObDereferenceObject(pFileObject); if( bReleaseSectionObject)