Windows: EOF for Synchronous Deferred Writes on XP/2003
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSWrite.cpp
index 328ca84..05a715d 100644 (file)
@@ -415,39 +415,73 @@ AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
                 }
             }
 
-            if (!CcCanIWrite( pFileObject,
-                              ulByteCount,
-                              FALSE,
-                              bRetry))
-            {
+           //
+           // 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)
+           {
 
-                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" : ""));
+               while (!CcCanIWrite( pFileObject,
+                                    ulByteCount,
+                                    FALSE,
+                                    bRetry))
+               {
+                   static const LONGLONG llWriteDelay = (LONGLONG)-100000;
+                   bRetry = TRUE;
 
-                ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
+                   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);
 
-                if ( STATUS_PENDING == ntStatus)
-                {
+                   KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
+               }
+           }
+           else
+           {
 
-                    bCompleteIrp = FALSE;
-                }
-                else
-                {
+               if (!CcCanIWrite( pFileObject,
+                                 ulByteCount,
+                                 FALSE,
+                                 bRetry))
+               {
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
-                                  AFS_TRACE_LEVEL_ERROR,
-                                  "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
-                                  pFileObject,
-                                  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" : ""));
 
-                try_return( ntStatus);
-            }
+                   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);
+               }
+           }
         }
 
         //
@@ -723,7 +757,7 @@ try_exit:
             if ( !bPagingIo)
             {
 
-                if( bSynchronousFo)
+               if( bSynchronousFo)
                 {
 
                     pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;