2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include "AFSCommon.h"
43 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
45 IN LARGE_INTEGER StartingByte,
47 IN BOOLEAN ForceFlush);
50 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
52 IN LARGE_INTEGER StartingByte,
57 AFSExtendingWrite( IN AFSFcb *Fcb,
58 IN PFILE_OBJECT FileObject,
59 IN LONGLONG NewLength);
66 // This is the dispatch handler for the IRP_MJ_WRITE request
70 // A status is returned for the function
73 AFSWrite( IN PDEVICE_OBJECT LibDeviceObject,
77 NTSTATUS ntStatus = STATUS_SUCCESS;
82 ntStatus = AFSCommonWrite( AFSRDRDeviceObject, Irp, NULL);
84 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
87 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
94 AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
99 NTSTATUS ntStatus = STATUS_SUCCESS;
100 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
101 IO_STACK_LOCATION *pIrpSp;
104 AFSNonPagedFcb *pNPFcb = NULL;
105 ULONG ulByteCount = 0;
106 LARGE_INTEGER liStartingByte;
107 PFILE_OBJECT pFileObject;
108 BOOLEAN bPagingIo = FALSE;
109 BOOLEAN bNonCachedIo = FALSE;
110 BOOLEAN bReleaseMain = FALSE;
111 BOOLEAN bReleaseSectionObject = FALSE;
112 BOOLEAN bReleasePaging = FALSE;
113 BOOLEAN bExtendingWrite = FALSE;
114 BOOLEAN bCompleteIrp = TRUE;
116 HANDLE hCallingUser = OnBehalfOf;
117 ULONG ulExtensionLength = 0;
118 BOOLEAN bRetry = FALSE;
119 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
121 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
126 pFileObject = pIrpSp->FileObject;
129 // Extract the fileobject references
132 pFcb = (AFSFcb *)pFileObject->FsContext;
133 pCcb = (AFSCcb *)pFileObject->FsContext2;
135 ObReferenceObject( pFileObject);
140 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
141 AFS_TRACE_LEVEL_ERROR,
142 "AFSCommonWrite Attempted write (%08lX) when pFcb == NULL\n",
145 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
148 pNPFcb = pFcb->NPFcb;
151 // If we are in shutdown mode then fail the request
154 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
157 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
158 AFS_TRACE_LEVEL_WARNING,
159 "AFSCommonWrite (%08lX) Open request after shutdown\n",
162 try_return( ntStatus = STATUS_TOO_LATE);
165 liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
166 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
167 bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
168 ulByteCount = pIrpSp->Parameters.Write.Length;
170 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
171 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
172 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
175 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
176 AFS_TRACE_LEVEL_ERROR,
177 "AFSCommonWrite Attempted write (%08lX) on an invalid node type %08lX\n",
179 pFcb->Header.NodeTypeCode);
181 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
185 // If this is a write against an IOCtl node then handle it
186 // in a different pathway
189 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
192 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
193 AFS_TRACE_LEVEL_VERBOSE,
194 "AFSCommonWrite (%08lX) Processing file (PIOCTL) Offset %I64X Length %08lX Irp Flags %08lX\n",
196 liStartingByte.QuadPart,
200 ntStatus = AFSIOCtlWrite( DeviceObject,
203 try_return( ntStatus);
205 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
208 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
209 AFS_TRACE_LEVEL_VERBOSE,
210 "AFSCommonWrite (%08lX) Processing file (SHARE) Offset %I64X Length %08lX Irp Flags %08lX\n",
212 liStartingByte.QuadPart,
216 ntStatus = AFSShareWrite( DeviceObject,
219 try_return( ntStatus);
223 // Is the Cache not there yet? Exit.
225 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
226 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
229 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
230 AFS_TRACE_LEVEL_ERROR,
231 "AFSCommonWrite (%08lX) Request failed due to AFS cache closed\n",
234 try_return( ntStatus = STATUS_TOO_LATE );
237 if( pFcb->ObjectInformation->VolumeCB != NULL &&
238 BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.Characteristics, FILE_READ_ONLY_DEVICE))
241 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
242 AFS_TRACE_LEVEL_ERROR,
243 "AFSCommonWrite (%08lX) Request failed due to read only volume\n",
246 try_return( ntStatus = STATUS_ACCESS_DENIED);
250 // We need to know on whose behalf we have been called (which
251 // we will eventually tell to the server - for non paging
252 // writes). If we were posted then we were told. If this is
253 // the first time we saw the irp then we grab it now.
255 if( NULL == OnBehalfOf )
258 hCallingUser = PsGetCurrentProcessId();
263 hCallingUser = OnBehalfOf;
267 // Check for zero length write
270 if( ulByteCount == 0)
273 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
274 AFS_TRACE_LEVEL_VERBOSE,
275 "AFSCommonWrite (%08lX) Request completed due to zero length\n",
278 try_return( ntStatus);
282 // Is this Fcb valid???
285 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
288 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
289 AFS_TRACE_LEVEL_ERROR,
290 "AFSCommonWrite (%08lX) Failing request due to INVALID fcb\n",
293 Irp->IoStatus.Information = 0;
295 try_return( ntStatus = STATUS_FILE_DELETED);
298 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
299 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
302 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
303 AFS_TRACE_LEVEL_ERROR,
304 "AFSCommonWrite (%08lX) Request failed due to file deleted\n",
307 try_return( ntStatus = STATUS_FILE_DELETED);
310 if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
313 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
314 AFS_TRACE_LEVEL_VERBOSE,
315 "AFSCommonWrite (%08lX) IRP_MN_COMPLETE being processed\n",
318 CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
321 // Mdl is now Deallocated
324 Irp->MdlAddress = NULL;
326 try_return( ntStatus = STATUS_SUCCESS );
330 // If we get a non cached IO for a cached file we should do a purge.
331 // For now we will just promote to cached
333 if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
335 bNonCachedIo = FALSE;
338 if ( !bNonCachedIo) {
343 if( pFileObject->PrivateCacheMap == NULL)
346 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
347 AFS_TRACE_LEVEL_VERBOSE,
348 "AFSCommonWrite Acquiring Fcb SectionObject lock %08lX EXCL %08lX\n",
349 &pNPFcb->SectionObjectResource,
350 PsGetCurrentThread());
352 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
355 bReleaseSectionObject = TRUE;
360 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
361 AFS_TRACE_LEVEL_VERBOSE,
362 "AFSCommonWrite Initialize caching on Fcb %08lX FileObject %08lX\n",
366 CcInitializeCacheMap( pFileObject,
367 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
369 AFSLibCacheManagerCallbacks,
372 CcSetReadAheadGranularity( pFileObject,
373 pDeviceExt->Specific.RDR.MaximumRPCLength);
375 CcSetDirtyPageThreshold( pFileObject,
376 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength);
378 __except( EXCEPTION_EXECUTE_HANDLER)
381 ntStatus = GetExceptionCode();
383 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
384 AFS_TRACE_LEVEL_ERROR,
385 "AFSCommonWrite (%08lX) Exception thrown while initializing cache map Status %08lX\n",
390 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
391 AFS_TRACE_LEVEL_VERBOSE,
392 "AFSCommonWrite Releasing Fcb SectionObject lock %08lX EXCL %08lX\n",
393 &pNPFcb->SectionObjectResource,
394 PsGetCurrentThread());
396 AFSReleaseResource( &pNPFcb->SectionObjectResource);
398 bReleaseSectionObject = FALSE;
401 if( !NT_SUCCESS( ntStatus))
404 try_return( ntStatus);
409 while (!CcCanIWrite( pFileObject,
414 static const LONGLONG llWriteDelay = (LONGLONG)-100000;
416 KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
421 // Save off the PID if this is not a paging IO
425 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
426 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
427 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
430 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
432 if( ullProcessId == (ULONGLONG)AFSSysProcess)
434 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
435 AFS_TRACE_LEVEL_WARNING,
436 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
445 // - if Paging then we need to do nothing (the precalls will
446 // have acquired the paging resource), for clarity we will collect
447 // the paging resource
448 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
449 // - Otherwise we collect the file shared, check against extending and
460 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
462 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
463 AFS_TRACE_LEVEL_VERBOSE,
464 "AFSCommonWrite Acquiring Fcb PagingIo lock %08lX SHARED %08lX\n",
465 &pNPFcb->PagingResource,
466 PsGetCurrentThread());
468 AFSAcquireShared( &pNPFcb->PagingResource,
471 bReleasePaging = TRUE;
474 // We have the correct lock - we cannot have the wrong one
481 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
482 pFcb->Header.FileSize.QuadPart) ||
483 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
484 liStartingByte.HighPart == -1)) ;
489 // Check for lock inversion
492 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
494 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
495 AFS_TRACE_LEVEL_VERBOSE,
496 "AFSCommonWrite Acquiring Fcb lock %08lX EXCL %08lX\n",
498 PsGetCurrentThread());
500 AFSAcquireExcl( &pNPFcb->Resource,
505 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
506 AFS_TRACE_LEVEL_VERBOSE,
507 "AFSCommonWrite Acquiring Fcb SectionObject lock %08lX EXCL %08lX\n",
508 &pNPFcb->SectionObjectResource,
509 PsGetCurrentThread());
511 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
514 bReleaseSectionObject = TRUE;
516 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
517 liStartingByte.HighPart == -1)
519 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
521 liStartingByte = pFcb->Header.ValidDataLength;
525 liStartingByte = pFcb->Header.FileSize;
530 // We have the correct lock - even if we don't end up truncating
536 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
538 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
539 AFS_TRACE_LEVEL_VERBOSE,
540 "AFSCommonWrite Acquiring Fcb lock %08lX SHARED %08lX\n",
542 PsGetCurrentThread());
544 AFSAcquireShared( &pNPFcb->Resource,
549 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
550 AFS_TRACE_LEVEL_VERBOSE,
551 "AFSCommonWrite Acquiring Fcb SectionObject lock %08lX SHARED %08lX\n",
552 &pNPFcb->SectionObjectResource,
553 PsGetCurrentThread());
555 AFSAcquireShared( &pNPFcb->SectionObjectResource,
558 bReleaseSectionObject = TRUE;
561 // Have things moved? Are we extending? If so, the the lock isn't OK
563 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
567 AFSReleaseResource( &pNPFcb->Resource);
569 bReleaseMain = FALSE;
580 // Check the BR locks on the file.
583 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
587 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
588 AFS_TRACE_LEVEL_ERROR,
589 "AFSCommonWrite (%08lX) Request failed due to lock conflict\n",
592 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
598 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
600 if( !NT_SUCCESS(ntStatus))
603 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
604 AFS_TRACE_LEVEL_ERROR,
605 "AFSCommonWrite (%08lX) Failed extending write request Status %08lX\n",
609 try_return( ntStatus );
615 // Fire off the request as appropriate
617 bCompleteIrp = FALSE;
624 // Main and SectionObject resources held Shared
627 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
628 AFS_TRACE_LEVEL_VERBOSE,
629 "AFSCommonWrite (%08lX) Processing CACHED request Offset %I64X Len %08lX\n",
631 liStartingByte.QuadPart,
634 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, TRUE);
641 // if bPagingIo, Paging Resource held Shared
642 // else Main and SectionObject resources held Shared
645 if( bReleaseSectionObject)
648 AFSReleaseResource( &pNPFcb->SectionObjectResource);
650 bReleaseSectionObject = FALSE;
656 AFSReleaseResource( &pNPFcb->PagingResource);
658 bReleasePaging = FALSE;
664 AFSReleaseResource( &pNPFcb->Resource);
666 bReleaseMain = FALSE;
669 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
670 AFS_TRACE_LEVEL_VERBOSE,
671 "AFSCommonWrite (%08lX) Processing NON-CACHED request Offset %I64X Len %08lX\n",
673 liStartingByte.QuadPart,
676 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
681 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
682 AFS_TRACE_LEVEL_VERBOSE,
683 "AFSCommonWrite (%08lX) Process complete Status %08lX\n",
687 ObDereferenceObject(pFileObject);
689 if( bReleaseSectionObject)
692 AFSReleaseResource( &pNPFcb->SectionObjectResource);
698 AFSReleaseResource( &pNPFcb->PagingResource);
704 AFSReleaseResource( &pNPFcb->Resource);
710 AFSCompleteRequest( Irp,
719 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
723 NTSTATUS ntStatus = STATUS_SUCCESS;
724 AFSPIOCtlIORequestCB stIORequestCB;
725 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
728 AFSPIOCtlIOResultCB stIOResultCB;
729 ULONG ulBytesReturned = 0;
730 AFSFileID stParentFID;
735 RtlZeroMemory( &stIORequestCB,
736 sizeof( AFSPIOCtlIORequestCB));
738 if( pIrpSp->Parameters.Write.Length == 0)
742 // Nothing to do in this case
745 try_return( ntStatus);
748 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
750 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
752 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
753 AFS_TRACE_LEVEL_VERBOSE,
754 "AFSIOCtlWrite Acquiring Fcb lock %08lX SHARED %08lX\n",
755 &pFcb->NPFcb->Resource,
756 PsGetCurrentThread());
758 AFSAcquireShared( &pFcb->NPFcb->Resource,
762 // Get the parent fid to pass to the cm
765 RtlZeroMemory( &stParentFID,
768 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
772 // The parent directory FID of the node
775 stParentFID = pFcb->ObjectInformation->ParentObjectInformation->FileId;
779 // Set the control block up
782 stIORequestCB.RequestId = pCcb->RequestID;
784 if( pFcb->ObjectInformation->VolumeCB != NULL)
786 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
790 // Lock down the buffer
793 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
794 pIrpSp->Parameters.Write.Length);
796 if( stIORequestCB.MappedBuffer == NULL)
799 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
802 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
804 stIOResultCB.BytesProcessed = 0;
806 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
809 // Issue the request to the service
812 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
813 AFS_REQUEST_FLAG_SYNCHRONOUS,
817 (void *)&stIORequestCB,
818 sizeof( AFSPIOCtlIORequestCB),
822 if( !NT_SUCCESS( ntStatus))
825 try_return( ntStatus);
829 // Update the length written
832 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
836 if( stIORequestCB.MappedBuffer != NULL)
839 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
846 AFSReleaseResource( &pFcb->NPFcb->Resource);
854 // This function is called when we know we have to read from the AFS Cache.
856 // It ensures that we have exents for the entirety of the write and
857 // then pins the extents into memory (meaning that although we may
858 // add we will not remove). Then it creates a scatter gather write
859 // and fires off the IRPs
863 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
865 IN LARGE_INTEGER StartingByte,
868 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
869 VOID *pSystemBuffer = NULL;
870 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
871 BOOLEAN bLocked = FALSE;
872 BOOLEAN bCompleteIrp = TRUE;
873 BOOLEAN bExtentsMapped = FALSE;
874 AFSGatherIo *pGatherIo = NULL;
875 AFSIoRun *pIoRuns = NULL;
876 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
877 ULONG extentsCount = 0, runCount = 0;
878 AFSExtent *pStartExtent = NULL;
879 AFSExtent *pIgnoreExtent = NULL;
880 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
881 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
882 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
883 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
884 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
885 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
886 ULONG ulRequestCount = 0;
887 LARGE_INTEGER liCurrentTime, liLastRequestTime;
888 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
889 PFILE_OBJECT pCacheFileObject = NULL;
890 BOOLEAN bDerefExtents = FALSE;
894 Irp->IoStatus.Information = 0;
896 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
899 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
900 AFS_TRACE_LEVEL_ERROR,
901 "AFSNonCachedWrite (%08lX) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
904 pIrpSp->Parameters.Write.Length,
905 pDevExt->Specific.RDR.MaxIo.QuadPart);
907 try_return( ntStatus = STATUS_UNSUCCESSFUL);
911 // Get the mapping for the buffer
913 pSystemBuffer = AFSLockSystemBuffer( Irp,
916 if( pSystemBuffer == NULL)
919 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
920 AFS_TRACE_LEVEL_ERROR,
921 "AFSNonCachedWrite (%08lX) Failed to map system buffer\n",
924 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
929 // Provoke a get of the extents - if we need to.
932 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
933 AFS_TRACE_LEVEL_VERBOSE,
934 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
935 pFcb->ObjectInformation->FileId.Cell,
936 pFcb->ObjectInformation->FileId.Volume,
937 pFcb->ObjectInformation->FileId.Vnode,
938 pFcb->ObjectInformation->FileId.Unique,
939 StartingByte.QuadPart,
942 ntStatus = AFSRequestExtentsAsync( pFcb,
947 if (!NT_SUCCESS(ntStatus))
950 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
951 AFS_TRACE_LEVEL_ERROR,
952 "AFSNonCachedWrite (%08lX) Failed to request extents Status %08lX\n",
956 try_return( ntStatus);
959 KeQueryTickCount( &liLastRequestTime);
964 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
965 AFS_TRACE_LEVEL_VERBOSE,
966 "AFSNonCachedWrite Acquiring Fcb extents lock %08lX SHARED %08lX\n",
967 &pFcb->NPFcb->Specific.File.ExtentsResource,
968 PsGetCurrentThread());
970 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
972 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
976 pIgnoreExtent = NULL;
978 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
983 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
985 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
986 AFS_TRACE_LEVEL_VERBOSE,
987 "AFSNonCachedWrite Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
988 &pFcb->NPFcb->Specific.File.ExtentsResource,
989 PsGetCurrentThread());
991 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
995 // We will re-request the extents after waiting for them
998 KeQueryTickCount( &liCurrentTime);
1000 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1003 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1004 AFS_TRACE_LEVEL_VERBOSE,
1005 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
1006 pFcb->ObjectInformation->FileId.Cell,
1007 pFcb->ObjectInformation->FileId.Volume,
1008 pFcb->ObjectInformation->FileId.Vnode,
1009 pFcb->ObjectInformation->FileId.Unique,
1010 StartingByte.QuadPart,
1013 ntStatus = AFSRequestExtentsAsync( pFcb,
1018 if (!NT_SUCCESS(ntStatus))
1021 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1022 AFS_TRACE_LEVEL_ERROR,
1023 "AFSNonCachedWrite (%08lX) Failed to request extents Status %08lX\n",
1027 try_return( ntStatus);
1030 KeQueryTickCount( &liLastRequestTime);
1034 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1035 AFS_TRACE_LEVEL_VERBOSE,
1036 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
1037 pFcb->ObjectInformation->FileId.Cell,
1038 pFcb->ObjectInformation->FileId.Volume,
1039 pFcb->ObjectInformation->FileId.Vnode,
1040 pFcb->ObjectInformation->FileId.Unique,
1041 StartingByte.QuadPart,
1048 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1050 if (!NT_SUCCESS(ntStatus))
1053 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1054 AFS_TRACE_LEVEL_ERROR,
1055 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
1056 pFcb->ObjectInformation->FileId.Cell,
1057 pFcb->ObjectInformation->FileId.Volume,
1058 pFcb->ObjectInformation->FileId.Vnode,
1059 pFcb->ObjectInformation->FileId.Unique,
1060 StartingByte.QuadPart,
1064 try_return( ntStatus);
1069 // As per the read path -
1072 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1073 AFS_TRACE_LEVEL_VERBOSE,
1074 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
1075 pFcb->ObjectInformation->FileId.Cell,
1076 pFcb->ObjectInformation->FileId.Volume,
1077 pFcb->ObjectInformation->FileId.Vnode,
1078 pFcb->ObjectInformation->FileId.Unique,
1079 StartingByte.QuadPart,
1082 ntStatus = AFSGetExtents( pFcb,
1089 if (!NT_SUCCESS(ntStatus))
1092 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1093 AFS_TRACE_LEVEL_ERROR,
1094 "AFSNonCachedWrite (%08lX) Failed to retrieve mapped extents Status %08lX\n",
1098 try_return( ntStatus );
1101 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1102 AFS_TRACE_LEVEL_VERBOSE,
1103 "AFSNonCachedWrite (%08lX) Successfully retrieved map extents count %08lX run count %08lX\n",
1108 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1111 Irp->IoStatus.Information = ByteCount;
1115 // Setup the MD5 for each extent
1118 AFSSetupMD5Hash( pFcb,
1126 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1132 if (!NT_SUCCESS(ntStatus))
1135 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1136 AFS_TRACE_LEVEL_ERROR,
1137 "AFSNonCachedWrite (%08lX) Failed to process extent run for non-persistent cache Status %08lX\n",
1142 try_return( ntStatus);
1146 // Retrieve the cache file object
1149 pCacheFileObject = AFSReferenceCacheFileObject();
1151 if( pCacheFileObject == NULL)
1154 ntStatus = STATUS_DEVICE_NOT_READY;
1156 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1157 AFS_TRACE_LEVEL_ERROR,
1158 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
1159 pFcb->ObjectInformation->FileId.Cell,
1160 pFcb->ObjectInformation->FileId.Volume,
1161 pFcb->ObjectInformation->FileId.Vnode,
1162 pFcb->ObjectInformation->FileId.Unique,
1163 StartingByte.QuadPart,
1167 try_return( ntStatus);
1170 if (runCount > AFS_MAX_STACK_IO_RUNS)
1173 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1174 runCount * sizeof( AFSIoRun ),
1176 if (NULL == pIoRuns)
1179 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1180 AFS_TRACE_LEVEL_ERROR,
1181 "AFSNonCachedWrite (%08lX) Failed to allocate IO run block\n",
1184 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1193 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1195 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1204 if (!NT_SUCCESS(ntStatus))
1207 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1208 AFS_TRACE_LEVEL_ERROR,
1209 "AFSNonCachedWrite (%08lX) Failed to initialize IO run block Status %08lX\n",
1213 try_return( ntStatus );
1216 AFSReferenceActiveExtents( pStartExtent,
1219 bDerefExtents = TRUE;
1221 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1222 AFS_TRACE_LEVEL_VERBOSE,
1223 "AFSNonCachedWrite Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
1224 &pFcb->NPFcb->Specific.File.ExtentsResource,
1225 PsGetCurrentThread());
1227 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1230 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1231 sizeof( AFSGatherIo),
1234 if (NULL == pGatherIo)
1237 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1238 AFS_TRACE_LEVEL_ERROR,
1239 "AFSNonCachedWrite (%08lX) Failed to allocate IO gather block\n",
1242 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1243 AFS_TRACE_LEVEL_VERBOSE,
1244 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %08lX SHARED %08lX\n",
1245 &pFcb->NPFcb->Specific.File.ExtentsResource,
1246 PsGetCurrentThread());
1248 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1252 AFSDereferenceActiveExtents( pStartExtent,
1255 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1258 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1261 // Initialize count to 1, that was we won't get an early
1262 // completion if the first irp completes before the second is
1265 pGatherIo->Count = 1;
1266 pGatherIo->Status = STATUS_SUCCESS;
1267 pGatherIo->MasterIrp = Irp;
1268 pGatherIo->Synchronous = TRUE;
1269 pGatherIo->CompleteMasterIrp = FALSE;
1271 bCompleteIrp = TRUE;
1273 if( pGatherIo->Synchronous)
1275 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1280 // Setup the MD5 for each extent
1283 AFSSetupMD5Hash( pFcb,
1292 // Pre-emptively set up the count
1295 Irp->IoStatus.Information = ByteCount;
1297 ntStatus = AFSQueueStartIos( pCacheFileObject,
1299 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1304 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1305 AFS_TRACE_LEVEL_VERBOSE,
1306 "AFSNonCachedWrite (%08lX) AFSStartIos completed Status %08lX\n",
1310 if( !NT_SUCCESS( ntStatus))
1313 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1314 AFS_TRACE_LEVEL_VERBOSE,
1315 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %08lX SHARED %08lX\n",
1316 &pFcb->NPFcb->Specific.File.ExtentsResource,
1317 PsGetCurrentThread());
1319 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1323 AFSDereferenceActiveExtents( pStartExtent,
1326 try_return( ntStatus);
1330 // Wait for completion of All IOs we started.
1333 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1339 if( NT_SUCCESS( ntStatus))
1342 ntStatus = pGatherIo->Status;
1345 if( !NT_SUCCESS( ntStatus))
1348 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1349 AFS_TRACE_LEVEL_VERBOSE,
1350 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %08lX SHARED %08lX\n",
1351 &pFcb->NPFcb->Specific.File.ExtentsResource,
1352 PsGetCurrentThread());
1354 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1358 AFSDereferenceActiveExtents( pStartExtent,
1361 try_return( ntStatus);
1366 if( NT_SUCCESS( ntStatus) &&
1367 pStartExtent != NULL &&
1368 Irp->IoStatus.Information > 0)
1374 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1380 // Since this is dirty we can mark the extents dirty now.
1381 // AFSMarkDirty will dereference the extents. Do not call
1382 // AFSDereferenceActiveExtents() in this code path.
1394 // This was an uncached user write - tell the server to do
1395 // the flush when the worker thread next wakes up
1397 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1401 if( pCacheFileObject != NULL)
1403 AFSReleaseCacheFileObject( pCacheFileObject);
1406 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1407 AFS_TRACE_LEVEL_VERBOSE,
1408 "AFSNonCachedWrite (%08lX) Completed request Status %08lX\n",
1412 if (NT_SUCCESS(ntStatus) &&
1417 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1423 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1424 AFS_TRACE_LEVEL_VERBOSE,
1425 "AFSNonCachedWrite Releasing Fcb extents lock %08lX SHARED %08lX\n",
1426 &pFcb->NPFcb->Specific.File.ExtentsResource,
1427 PsGetCurrentThread());
1429 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1434 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1437 if( NULL != pIoRuns &&
1438 stIoRuns != pIoRuns)
1440 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1446 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1447 AFS_TRACE_LEVEL_VERBOSE,
1448 "AFSNonCachedWrite Completing Irp %08lX Status %08lX Info %08lX\n",
1451 Irp->IoStatus.Information);
1453 AFSCompleteRequest( Irp, ntStatus);
1462 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1464 IN LARGE_INTEGER StartingByte,
1466 IN BOOLEAN ForceFlush)
1468 PVOID pSystemBuffer = NULL;
1469 NTSTATUS ntStatus = STATUS_SUCCESS;
1470 IO_STATUS_BLOCK iosbFlush;
1471 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1472 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1473 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1474 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1475 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1476 BOOLEAN bMapped = FALSE;
1477 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1478 PMDL pCurrentMdl = Irp->MdlAddress;
1479 LARGE_INTEGER liCurrentOffset;
1484 Irp->IoStatus.Information = 0;
1486 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1492 CcPrepareMdlWrite( pFileObject,
1498 ntStatus = Irp->IoStatus.Status;
1500 __except( EXCEPTION_EXECUTE_HANDLER)
1502 ntStatus = GetExceptionCode();
1504 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1505 AFS_TRACE_LEVEL_ERROR,
1506 "AFSCachedWrite (%08lX) Exception thrown while preparing mdl write Status %08lX\n",
1511 if( !NT_SUCCESS( ntStatus))
1515 // Free up any potentially allocated mdl's
1518 CcMdlWriteComplete( pFileObject,
1522 Irp->MdlAddress = NULL;
1524 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1525 AFS_TRACE_LEVEL_ERROR,
1526 "AFSCachedWrite (%08lX) Failed to process MDL write Status %08lX\n",
1531 try_return( ntStatus);
1534 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1536 while( ulTotalLen > 0)
1539 ntStatus = STATUS_SUCCESS;
1541 if( pCurrentMdl != NULL)
1544 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1545 NormalPagePriority);
1547 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1549 if( ulCurrentIO > ulTotalLen)
1551 ulCurrentIO = ulTotalLen;
1557 pSystemBuffer = AFSLockSystemBuffer( Irp,
1560 ulCurrentIO = ulTotalLen;
1563 if( pSystemBuffer == NULL)
1566 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1567 AFS_TRACE_LEVEL_ERROR,
1568 "AFSCachedWrite (%08lX) Failed to lock system buffer\n",
1571 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1577 if( !CcCopyWrite( pFileObject,
1584 // Failed to process request.
1587 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1588 AFS_TRACE_LEVEL_ERROR,
1589 "AFSCachedWrite (%08lX) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1591 &pFileObject->FileName,
1592 liCurrentOffset.QuadPart,
1593 Irp->IoStatus.Status);
1595 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1598 __except( EXCEPTION_EXECUTE_HANDLER)
1601 ntStatus = GetExceptionCode();
1603 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1604 AFS_TRACE_LEVEL_ERROR,
1605 "AFSCachedWrite (%08lX) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1607 &pFileObject->FileName,
1608 liCurrentOffset.QuadPart,
1612 if( !NT_SUCCESS( ntStatus))
1614 try_return( ntStatus);
1618 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1622 // We have detected a file we do a write through with.
1625 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1630 if( !NT_SUCCESS( iosbFlush.Status))
1633 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1634 AFS_TRACE_LEVEL_ERROR,
1635 "AFSCachedWrite (%08lX) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1637 &pFileObject->FileName,
1638 pFcb->ObjectInformation->FileId.Cell,
1639 pFcb->ObjectInformation->FileId.Volume,
1640 pFcb->ObjectInformation->FileId.Vnode,
1641 pFcb->ObjectInformation->FileId.Unique,
1643 iosbFlush.Information);
1645 try_return( ntStatus = iosbFlush.Status);
1649 if( ulTotalLen <= ulCurrentIO)
1654 liCurrentOffset.QuadPart += ulCurrentIO;
1656 ulTotalLen -= ulCurrentIO;
1658 pCurrentMdl = pCurrentMdl->Next;
1663 if( NT_SUCCESS( ntStatus))
1666 Irp->IoStatus.Information = ByteCount;
1671 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1675 // If this extended the Vdl, then update it accordingly
1678 if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1681 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1685 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1688 // Write through asked for... Set things so that we get
1689 // flush when the worker thread next wakes up
1691 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1694 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1697 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1699 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1703 AFSCompleteRequest( Irp,
1712 AFSExtendingWrite( IN AFSFcb *Fcb,
1713 IN PFILE_OBJECT FileObject,
1714 IN LONGLONG NewLength)
1716 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1717 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1718 NTSTATUS ntStatus = STATUS_SUCCESS;
1719 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
1721 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1724 Fcb->Header.AllocationSize.QuadPart = NewLength;
1726 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1729 if( NewLength > Fcb->Header.FileSize.QuadPart)
1732 Fcb->Header.FileSize.QuadPart = NewLength;
1734 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1741 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentObjectInformation->FileId,
1742 Fcb->ObjectInformation,
1745 if (NT_SUCCESS(ntStatus))
1748 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1750 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1753 // If the file is currently cached, then let the MM know about the extension
1756 if( CcIsFileCached( FileObject))
1758 CcSetFileSizes( FileObject,
1759 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1764 Fcb->Header.FileSize = liSaveFileSize;
1765 Fcb->Header.AllocationSize = liSaveAllocation;
1769 // DownConvert file resource to shared
1771 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
1777 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
1781 NTSTATUS ntStatus = STATUS_SUCCESS;
1782 AFSPIOCtlIORequestCB stIORequestCB;
1783 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1784 AFSFcb *pFcb = NULL;
1785 AFSCcb *pCcb = NULL;
1786 AFSPipeIORequestCB *pIoRequest = NULL;
1787 void *pBuffer = NULL;
1788 AFSPipeIOResultCB stIoResult;
1789 ULONG ulBytesReturned = 0;
1794 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1796 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1798 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1799 AFS_TRACE_LEVEL_VERBOSE,
1800 "AFSShareWrite On pipe %wZ Length %08lX\n",
1801 &pCcb->DirectoryCB->NameInformation.FileName,
1802 pIrpSp->Parameters.Write.Length);
1804 if( pIrpSp->Parameters.Write.Length == 0)
1808 // Nothing to do in this case
1811 try_return( ntStatus);
1815 // Retrieve the buffer for the read request
1818 pBuffer = AFSLockSystemBuffer( Irp,
1819 pIrpSp->Parameters.Write.Length);
1821 if( pBuffer == NULL)
1824 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1825 AFS_TRACE_LEVEL_ERROR,
1826 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
1827 &pCcb->DirectoryCB->NameInformation.FileName);
1829 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1832 AFSAcquireShared( &pFcb->NPFcb->Resource,
1835 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1836 sizeof( AFSPipeIORequestCB) +
1837 pIrpSp->Parameters.Write.Length,
1838 AFS_GENERIC_MEMORY_14_TAG);
1840 if( pIoRequest == NULL)
1843 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1846 RtlZeroMemory( pIoRequest,
1847 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
1849 pIoRequest->RequestId = pCcb->RequestID;
1851 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1853 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
1855 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
1857 pIrpSp->Parameters.Write.Length);
1859 stIoResult.BytesProcessed = 0;
1861 ulBytesReturned = sizeof( AFSPipeIOResultCB);
1864 // Issue the open request to the service
1867 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
1868 AFS_REQUEST_FLAG_SYNCHRONOUS,
1870 &pCcb->DirectoryCB->NameInformation.FileName,
1873 sizeof( AFSPipeIORequestCB) +
1874 pIrpSp->Parameters.Write.Length,
1878 if( !NT_SUCCESS( ntStatus))
1881 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1882 AFS_TRACE_LEVEL_ERROR,
1883 "AFSShareWrite (%08lX) Failed service write Status %08lX\n",
1887 try_return( ntStatus);
1890 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1891 AFS_TRACE_LEVEL_VERBOSE,
1892 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
1893 &pCcb->DirectoryCB->NameInformation.FileName,
1894 stIoResult.BytesProcessed);
1896 Irp->IoStatus.Information = stIoResult.BytesProcessed;
1903 AFSReleaseResource( &pFcb->NPFcb->Resource);
1906 if( pIoRequest != NULL)
1909 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);