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 UNREFERENCED_PARAMETER(LibDeviceObject);
78 NTSTATUS ntStatus = STATUS_SUCCESS;
83 ntStatus = AFSCommonWrite( AFSRDRDeviceObject, Irp, NULL);
85 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
88 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
95 AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
100 NTSTATUS ntStatus = STATUS_SUCCESS;
101 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
102 IO_STACK_LOCATION *pIrpSp;
105 AFSNonPagedFcb *pNPFcb = NULL;
106 ULONG ulByteCount = 0;
107 LARGE_INTEGER liStartingByte;
108 PFILE_OBJECT pFileObject;
109 BOOLEAN bPagingIo = FALSE;
110 BOOLEAN bNonCachedIo = FALSE;
111 BOOLEAN bReleaseMain = FALSE;
112 BOOLEAN bReleaseSectionObject = FALSE;
113 BOOLEAN bReleasePaging = FALSE;
114 BOOLEAN bExtendingWrite = FALSE;
115 BOOLEAN bCompleteIrp = TRUE;
117 HANDLE hCallingUser = OnBehalfOf;
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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 (%p) 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 %p 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 %p FileObject %p\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 / 4096);
378 __except( EXCEPTION_EXECUTE_HANDLER)
381 ntStatus = GetExceptionCode();
383 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
384 AFS_TRACE_LEVEL_ERROR,
385 "AFSCommonWrite (%p) 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 %p 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;
417 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
418 AFS_TRACE_LEVEL_WARNING,
419 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for %u bytes! Retry in 10ms\n",
423 KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
428 // Save off the PID if this is not a paging IO
432 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
433 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
434 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
437 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
439 if( ullProcessId == (ULONGLONG)AFSSysProcess)
441 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
442 AFS_TRACE_LEVEL_WARNING,
443 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
452 // - if Paging then we need to do nothing (the precalls will
453 // have acquired the paging resource), for clarity we will collect
454 // the paging resource
455 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
456 // - Otherwise we collect the file shared, check against extending and
467 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
469 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
470 AFS_TRACE_LEVEL_VERBOSE,
471 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
472 &pNPFcb->PagingResource,
473 PsGetCurrentThread());
475 AFSAcquireShared( &pNPFcb->PagingResource,
478 bReleasePaging = TRUE;
481 // We have the correct lock - we cannot have the wrong one
488 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
489 pFcb->Header.FileSize.QuadPart) ||
490 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
491 liStartingByte.HighPart == -1)) ;
496 // Check for lock inversion
499 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
501 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
502 AFS_TRACE_LEVEL_VERBOSE,
503 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
505 PsGetCurrentThread());
507 AFSAcquireExcl( &pNPFcb->Resource,
512 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
513 AFS_TRACE_LEVEL_VERBOSE,
514 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
515 &pNPFcb->SectionObjectResource,
516 PsGetCurrentThread());
518 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
521 bReleaseSectionObject = TRUE;
523 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
524 liStartingByte.HighPart == -1)
526 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
528 liStartingByte = pFcb->Header.ValidDataLength;
532 liStartingByte = pFcb->Header.FileSize;
537 // We have the correct lock - even if we don't end up truncating
543 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
545 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
546 AFS_TRACE_LEVEL_VERBOSE,
547 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
549 PsGetCurrentThread());
551 AFSAcquireShared( &pNPFcb->Resource,
556 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
557 AFS_TRACE_LEVEL_VERBOSE,
558 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
559 &pNPFcb->SectionObjectResource,
560 PsGetCurrentThread());
562 AFSAcquireShared( &pNPFcb->SectionObjectResource,
565 bReleaseSectionObject = TRUE;
568 // Have things moved? Are we extending? If so, the the lock isn't OK
570 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
574 AFSReleaseResource( &pNPFcb->Resource);
576 bReleaseMain = FALSE;
587 // Check the BR locks on the file.
590 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
594 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
595 AFS_TRACE_LEVEL_ERROR,
596 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
599 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
605 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
607 if( !NT_SUCCESS(ntStatus))
610 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
611 AFS_TRACE_LEVEL_ERROR,
612 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
616 try_return( ntStatus );
622 // Fire off the request as appropriate
624 bCompleteIrp = FALSE;
631 // Main and SectionObject resources held Shared
634 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
635 AFS_TRACE_LEVEL_VERBOSE,
636 "AFSCommonWrite (%p) Processing CACHED request Offset %I64X Len %08lX\n",
638 liStartingByte.QuadPart,
641 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, TRUE);
648 // if bPagingIo, Paging Resource held Shared
649 // else Main and SectionObject resources held Shared
652 if( bReleaseSectionObject)
655 AFSReleaseResource( &pNPFcb->SectionObjectResource);
657 bReleaseSectionObject = FALSE;
663 AFSReleaseResource( &pNPFcb->PagingResource);
665 bReleasePaging = FALSE;
671 AFSReleaseResource( &pNPFcb->Resource);
673 bReleaseMain = FALSE;
676 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
677 AFS_TRACE_LEVEL_VERBOSE,
678 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %I64X Len %08lX\n",
680 liStartingByte.QuadPart,
683 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
688 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
689 AFS_TRACE_LEVEL_VERBOSE,
690 "AFSCommonWrite (%p) Process complete Status %08lX\n",
694 ObDereferenceObject(pFileObject);
696 if( bReleaseSectionObject)
699 AFSReleaseResource( &pNPFcb->SectionObjectResource);
705 AFSReleaseResource( &pNPFcb->PagingResource);
711 AFSReleaseResource( &pNPFcb->Resource);
717 AFSCompleteRequest( Irp,
726 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
730 UNREFERENCED_PARAMETER(DeviceObject);
731 NTSTATUS ntStatus = STATUS_SUCCESS;
732 AFSPIOCtlIORequestCB stIORequestCB;
733 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
736 AFSPIOCtlIOResultCB stIOResultCB;
737 ULONG ulBytesReturned = 0;
738 AFSFileID stParentFID;
743 RtlZeroMemory( &stIORequestCB,
744 sizeof( AFSPIOCtlIORequestCB));
746 if( pIrpSp->Parameters.Write.Length == 0)
750 // Nothing to do in this case
753 try_return( ntStatus);
756 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
758 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
760 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
761 AFS_TRACE_LEVEL_VERBOSE,
762 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
763 &pFcb->NPFcb->Resource,
764 PsGetCurrentThread());
766 AFSAcquireShared( &pFcb->NPFcb->Resource,
770 // Get the parent fid to pass to the cm
773 RtlZeroMemory( &stParentFID,
776 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
780 // The parent directory FID of the node
783 stParentFID = pFcb->ObjectInformation->ParentFileId;
787 // Set the control block up
790 stIORequestCB.RequestId = pCcb->RequestID;
792 if( pFcb->ObjectInformation->VolumeCB != NULL)
794 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
798 // Lock down the buffer
801 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
802 pIrpSp->Parameters.Write.Length);
804 if( stIORequestCB.MappedBuffer == NULL)
807 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
810 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
812 stIOResultCB.BytesProcessed = 0;
814 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
817 // Issue the request to the service
820 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
821 AFS_REQUEST_FLAG_SYNCHRONOUS,
825 (void *)&stIORequestCB,
826 sizeof( AFSPIOCtlIORequestCB),
830 if( !NT_SUCCESS( ntStatus))
833 try_return( ntStatus);
837 // Update the length written
840 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
844 if( stIORequestCB.MappedBuffer != NULL)
847 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
854 AFSReleaseResource( &pFcb->NPFcb->Resource);
862 // This function is called when we know we have to read from the AFS Cache.
864 // It ensures that we have exents for the entirety of the write and
865 // then pins the extents into memory (meaning that although we may
866 // add we will not remove). Then it creates a scatter gather write
867 // and fires off the IRPs
871 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
873 IN LARGE_INTEGER StartingByte,
876 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
877 VOID *pSystemBuffer = NULL;
878 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
879 BOOLEAN bLocked = FALSE;
880 BOOLEAN bCompleteIrp = TRUE;
881 AFSGatherIo *pGatherIo = NULL;
882 AFSIoRun *pIoRuns = NULL;
883 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
884 ULONG extentsCount = 0, runCount = 0;
885 AFSExtent *pStartExtent = NULL;
886 AFSExtent *pIgnoreExtent = NULL;
887 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
888 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
889 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
890 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
891 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
892 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
893 LARGE_INTEGER liCurrentTime, liLastRequestTime;
894 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
895 PFILE_OBJECT pCacheFileObject = NULL;
896 BOOLEAN bDerefExtents = FALSE;
900 Irp->IoStatus.Information = 0;
902 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
903 AFS_TRACE_LEVEL_VERBOSE,
904 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
906 StartingByte.HighPart,
907 StartingByte.LowPart,
910 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
913 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
914 AFS_TRACE_LEVEL_ERROR,
915 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
918 pIrpSp->Parameters.Write.Length,
919 pDevExt->Specific.RDR.MaxIo.QuadPart);
921 try_return( ntStatus = STATUS_UNSUCCESSFUL);
925 // Get the mapping for the buffer
927 pSystemBuffer = AFSLockSystemBuffer( Irp,
930 if( pSystemBuffer == NULL)
933 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
934 AFS_TRACE_LEVEL_ERROR,
935 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
938 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
943 // Provoke a get of the extents - if we need to.
946 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
947 AFS_TRACE_LEVEL_VERBOSE,
948 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
949 pFcb->ObjectInformation->FileId.Cell,
950 pFcb->ObjectInformation->FileId.Volume,
951 pFcb->ObjectInformation->FileId.Vnode,
952 pFcb->ObjectInformation->FileId.Unique,
953 StartingByte.QuadPart,
956 ntStatus = AFSRequestExtentsAsync( pFcb,
961 if (!NT_SUCCESS(ntStatus))
964 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
965 AFS_TRACE_LEVEL_ERROR,
966 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
970 try_return( ntStatus);
973 KeQueryTickCount( &liLastRequestTime);
978 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
979 AFS_TRACE_LEVEL_VERBOSE,
980 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
981 &pFcb->NPFcb->Specific.File.ExtentsResource,
982 PsGetCurrentThread());
984 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
986 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
990 pIgnoreExtent = NULL;
992 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
997 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
999 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1000 AFS_TRACE_LEVEL_VERBOSE,
1001 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1002 &pFcb->NPFcb->Specific.File.ExtentsResource,
1003 PsGetCurrentThread());
1005 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1009 // We will re-request the extents after waiting for them
1012 KeQueryTickCount( &liCurrentTime);
1014 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1017 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1018 AFS_TRACE_LEVEL_VERBOSE,
1019 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
1020 pFcb->ObjectInformation->FileId.Cell,
1021 pFcb->ObjectInformation->FileId.Volume,
1022 pFcb->ObjectInformation->FileId.Vnode,
1023 pFcb->ObjectInformation->FileId.Unique,
1024 StartingByte.QuadPart,
1027 ntStatus = AFSRequestExtentsAsync( pFcb,
1032 if (!NT_SUCCESS(ntStatus))
1035 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1036 AFS_TRACE_LEVEL_ERROR,
1037 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1041 try_return( ntStatus);
1044 KeQueryTickCount( &liLastRequestTime);
1048 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1049 AFS_TRACE_LEVEL_VERBOSE,
1050 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
1051 pFcb->ObjectInformation->FileId.Cell,
1052 pFcb->ObjectInformation->FileId.Volume,
1053 pFcb->ObjectInformation->FileId.Vnode,
1054 pFcb->ObjectInformation->FileId.Unique,
1055 StartingByte.QuadPart,
1062 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1064 if (!NT_SUCCESS(ntStatus))
1067 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1068 AFS_TRACE_LEVEL_ERROR,
1069 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
1070 pFcb->ObjectInformation->FileId.Cell,
1071 pFcb->ObjectInformation->FileId.Volume,
1072 pFcb->ObjectInformation->FileId.Vnode,
1073 pFcb->ObjectInformation->FileId.Unique,
1074 StartingByte.QuadPart,
1078 try_return( ntStatus);
1083 // As per the read path -
1086 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1087 AFS_TRACE_LEVEL_VERBOSE,
1088 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
1089 pFcb->ObjectInformation->FileId.Cell,
1090 pFcb->ObjectInformation->FileId.Volume,
1091 pFcb->ObjectInformation->FileId.Vnode,
1092 pFcb->ObjectInformation->FileId.Unique,
1093 StartingByte.QuadPart,
1096 ntStatus = AFSGetExtents( pFcb,
1103 if (!NT_SUCCESS(ntStatus))
1106 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1107 AFS_TRACE_LEVEL_ERROR,
1108 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1112 try_return( ntStatus );
1115 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1116 AFS_TRACE_LEVEL_VERBOSE,
1117 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1122 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1125 Irp->IoStatus.Information = ByteCount;
1129 // Setup the MD5 for each extent
1132 AFSSetupMD5Hash( pFcb,
1140 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1146 if (!NT_SUCCESS(ntStatus))
1149 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1150 AFS_TRACE_LEVEL_ERROR,
1151 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1156 try_return( ntStatus);
1160 // Retrieve the cache file object
1163 pCacheFileObject = AFSReferenceCacheFileObject();
1165 if( pCacheFileObject == NULL)
1168 ntStatus = STATUS_DEVICE_NOT_READY;
1170 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1171 AFS_TRACE_LEVEL_ERROR,
1172 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
1173 pFcb->ObjectInformation->FileId.Cell,
1174 pFcb->ObjectInformation->FileId.Volume,
1175 pFcb->ObjectInformation->FileId.Vnode,
1176 pFcb->ObjectInformation->FileId.Unique,
1177 StartingByte.QuadPart,
1181 try_return( ntStatus);
1184 if (runCount > AFS_MAX_STACK_IO_RUNS)
1187 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1188 runCount * sizeof( AFSIoRun ),
1190 if (NULL == pIoRuns)
1193 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1194 AFS_TRACE_LEVEL_ERROR,
1195 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1198 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1207 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1209 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1218 if (!NT_SUCCESS(ntStatus))
1221 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1222 AFS_TRACE_LEVEL_ERROR,
1223 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1227 try_return( ntStatus );
1230 AFSReferenceActiveExtents( pStartExtent,
1233 bDerefExtents = TRUE;
1235 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1236 AFS_TRACE_LEVEL_VERBOSE,
1237 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1238 &pFcb->NPFcb->Specific.File.ExtentsResource,
1239 PsGetCurrentThread());
1241 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1244 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1245 sizeof( AFSGatherIo),
1248 if (NULL == pGatherIo)
1251 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1252 AFS_TRACE_LEVEL_ERROR,
1253 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1256 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1257 AFS_TRACE_LEVEL_VERBOSE,
1258 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1259 &pFcb->NPFcb->Specific.File.ExtentsResource,
1260 PsGetCurrentThread());
1262 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1266 AFSDereferenceActiveExtents( pStartExtent,
1269 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1272 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1275 // Initialize count to 1, that was we won't get an early
1276 // completion if the first irp completes before the second is
1279 pGatherIo->Count = 1;
1280 pGatherIo->Status = STATUS_SUCCESS;
1281 pGatherIo->MasterIrp = Irp;
1282 pGatherIo->Synchronous = TRUE;
1283 pGatherIo->CompleteMasterIrp = FALSE;
1285 bCompleteIrp = TRUE;
1287 if( pGatherIo->Synchronous)
1289 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1294 // Setup the MD5 for each extent
1297 AFSSetupMD5Hash( pFcb,
1306 // Pre-emptively set up the count
1309 Irp->IoStatus.Information = ByteCount;
1311 ntStatus = AFSQueueStartIos( pCacheFileObject,
1313 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1318 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1319 AFS_TRACE_LEVEL_VERBOSE,
1320 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1324 if( !NT_SUCCESS( ntStatus))
1327 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1328 AFS_TRACE_LEVEL_VERBOSE,
1329 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1330 &pFcb->NPFcb->Specific.File.ExtentsResource,
1331 PsGetCurrentThread());
1333 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1337 AFSDereferenceActiveExtents( pStartExtent,
1340 try_return( ntStatus);
1344 // Wait for completion of All IOs we started.
1347 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1353 if( NT_SUCCESS( ntStatus))
1356 ntStatus = pGatherIo->Status;
1359 if( !NT_SUCCESS( ntStatus))
1362 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1363 AFS_TRACE_LEVEL_VERBOSE,
1364 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1365 &pFcb->NPFcb->Specific.File.ExtentsResource,
1366 PsGetCurrentThread());
1368 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1372 AFSDereferenceActiveExtents( pStartExtent,
1375 try_return( ntStatus);
1380 if( NT_SUCCESS( ntStatus) &&
1381 pStartExtent != NULL &&
1382 Irp->IoStatus.Information > 0)
1388 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1394 // Since this is dirty we can mark the extents dirty now.
1395 // AFSMarkDirty will dereference the extents. Do not call
1396 // AFSDereferenceActiveExtents() in this code path.
1408 // This was an uncached user write - tell the server to do
1409 // the flush when the worker thread next wakes up
1411 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1415 if( pCacheFileObject != NULL)
1417 AFSReleaseCacheFileObject( pCacheFileObject);
1420 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1421 AFS_TRACE_LEVEL_VERBOSE,
1422 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1424 StartingByte.HighPart,
1425 StartingByte.LowPart,
1429 if (NT_SUCCESS(ntStatus) &&
1434 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1440 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1441 AFS_TRACE_LEVEL_VERBOSE,
1442 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1443 &pFcb->NPFcb->Specific.File.ExtentsResource,
1444 PsGetCurrentThread());
1446 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1451 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1454 if( NULL != pIoRuns &&
1455 stIoRuns != pIoRuns)
1457 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1463 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1464 AFS_TRACE_LEVEL_VERBOSE,
1465 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1468 Irp->IoStatus.Information);
1470 AFSCompleteRequest( Irp, ntStatus);
1479 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1481 IN LARGE_INTEGER StartingByte,
1483 IN BOOLEAN ForceFlush)
1485 UNREFERENCED_PARAMETER(DeviceObject);
1486 PVOID pSystemBuffer = NULL;
1487 NTSTATUS ntStatus = STATUS_SUCCESS;
1488 IO_STATUS_BLOCK iosbFlush;
1489 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1490 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1491 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1492 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1493 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1494 PMDL pCurrentMdl = Irp->MdlAddress;
1495 LARGE_INTEGER liCurrentOffset;
1500 Irp->IoStatus.Information = 0;
1502 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1508 CcPrepareMdlWrite( pFileObject,
1514 ntStatus = Irp->IoStatus.Status;
1516 __except( EXCEPTION_EXECUTE_HANDLER)
1518 ntStatus = GetExceptionCode();
1520 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1521 AFS_TRACE_LEVEL_ERROR,
1522 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1527 if( !NT_SUCCESS( ntStatus))
1531 // Free up any potentially allocated mdl's
1534 CcMdlWriteComplete( pFileObject,
1538 Irp->MdlAddress = NULL;
1540 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1541 AFS_TRACE_LEVEL_ERROR,
1542 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1547 try_return( ntStatus);
1550 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1552 while( ulTotalLen > 0)
1555 ntStatus = STATUS_SUCCESS;
1557 if( pCurrentMdl != NULL)
1560 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1561 NormalPagePriority);
1563 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1565 if( ulCurrentIO > ulTotalLen)
1567 ulCurrentIO = ulTotalLen;
1573 pSystemBuffer = AFSLockSystemBuffer( Irp,
1576 ulCurrentIO = ulTotalLen;
1579 if( pSystemBuffer == NULL)
1582 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1583 AFS_TRACE_LEVEL_ERROR,
1584 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1587 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1593 if( !CcCopyWrite( pFileObject,
1600 // Failed to process request.
1603 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1604 AFS_TRACE_LEVEL_ERROR,
1605 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1607 &pFileObject->FileName,
1608 liCurrentOffset.QuadPart,
1609 Irp->IoStatus.Status);
1611 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1614 __except( EXCEPTION_EXECUTE_HANDLER)
1617 ntStatus = GetExceptionCode();
1619 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1620 AFS_TRACE_LEVEL_ERROR,
1621 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1623 &pFileObject->FileName,
1624 liCurrentOffset.QuadPart,
1628 if( !NT_SUCCESS( ntStatus))
1630 try_return( ntStatus);
1634 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1638 // We have detected a file we do a write through with.
1641 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1646 if( !NT_SUCCESS( iosbFlush.Status))
1649 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1650 AFS_TRACE_LEVEL_ERROR,
1651 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1653 &pFileObject->FileName,
1654 pFcb->ObjectInformation->FileId.Cell,
1655 pFcb->ObjectInformation->FileId.Volume,
1656 pFcb->ObjectInformation->FileId.Vnode,
1657 pFcb->ObjectInformation->FileId.Unique,
1659 iosbFlush.Information);
1661 try_return( ntStatus = iosbFlush.Status);
1665 if( ulTotalLen <= ulCurrentIO)
1670 liCurrentOffset.QuadPart += ulCurrentIO;
1672 ulTotalLen -= ulCurrentIO;
1674 pCurrentMdl = pCurrentMdl->Next;
1679 if( NT_SUCCESS( ntStatus))
1682 Irp->IoStatus.Information = ByteCount;
1687 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1691 // If this extended the Vdl, then update it accordingly
1694 if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1697 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1701 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1704 // Write through asked for... Set things so that we get
1705 // flush when the worker thread next wakes up
1707 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1710 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1713 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1715 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1719 AFSCompleteRequest( Irp,
1728 AFSExtendingWrite( IN AFSFcb *Fcb,
1729 IN PFILE_OBJECT FileObject,
1730 IN LONGLONG NewLength)
1732 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1733 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1734 NTSTATUS ntStatus = STATUS_SUCCESS;
1735 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
1737 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1740 Fcb->Header.AllocationSize.QuadPart = NewLength;
1742 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1745 if( NewLength > Fcb->Header.FileSize.QuadPart)
1748 Fcb->Header.FileSize.QuadPart = NewLength;
1750 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1757 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
1758 Fcb->ObjectInformation,
1761 if (NT_SUCCESS(ntStatus))
1764 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1766 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1769 // If the file is currently cached, then let the MM know about the extension
1772 if( CcIsFileCached( FileObject))
1774 CcSetFileSizes( FileObject,
1775 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1780 Fcb->Header.FileSize = liSaveFileSize;
1781 Fcb->Header.AllocationSize = liSaveAllocation;
1785 // DownConvert file resource to shared
1787 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
1793 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
1797 UNREFERENCED_PARAMETER(DeviceObject);
1798 NTSTATUS ntStatus = STATUS_SUCCESS;
1799 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1800 AFSFcb *pFcb = NULL;
1801 AFSCcb *pCcb = NULL;
1802 AFSPipeIORequestCB *pIoRequest = NULL;
1803 void *pBuffer = NULL;
1804 AFSPipeIOResultCB stIoResult;
1805 ULONG ulBytesReturned = 0;
1810 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1812 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1814 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1815 AFS_TRACE_LEVEL_VERBOSE,
1816 "AFSShareWrite On pipe %wZ Length %08lX\n",
1817 &pCcb->DirectoryCB->NameInformation.FileName,
1818 pIrpSp->Parameters.Write.Length);
1820 if( pIrpSp->Parameters.Write.Length == 0)
1824 // Nothing to do in this case
1827 try_return( ntStatus);
1831 // Retrieve the buffer for the read request
1834 pBuffer = AFSLockSystemBuffer( Irp,
1835 pIrpSp->Parameters.Write.Length);
1837 if( pBuffer == NULL)
1840 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1841 AFS_TRACE_LEVEL_ERROR,
1842 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
1843 &pCcb->DirectoryCB->NameInformation.FileName);
1845 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1848 AFSAcquireShared( &pFcb->NPFcb->Resource,
1851 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
1852 sizeof( AFSPipeIORequestCB) +
1853 pIrpSp->Parameters.Write.Length,
1854 AFS_GENERIC_MEMORY_14_TAG);
1856 if( pIoRequest == NULL)
1859 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1862 RtlZeroMemory( pIoRequest,
1863 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
1865 pIoRequest->RequestId = pCcb->RequestID;
1867 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1869 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
1871 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
1873 pIrpSp->Parameters.Write.Length);
1875 stIoResult.BytesProcessed = 0;
1877 ulBytesReturned = sizeof( AFSPipeIOResultCB);
1880 // Issue the open request to the service
1883 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
1884 AFS_REQUEST_FLAG_SYNCHRONOUS,
1886 &pCcb->DirectoryCB->NameInformation.FileName,
1889 sizeof( AFSPipeIORequestCB) +
1890 pIrpSp->Parameters.Write.Length,
1894 if( !NT_SUCCESS( ntStatus))
1897 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1898 AFS_TRACE_LEVEL_ERROR,
1899 "AFSShareWrite (%p) Failed service write Status %08lX\n",
1903 try_return( ntStatus);
1906 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1907 AFS_TRACE_LEVEL_VERBOSE,
1908 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
1909 &pCcb->DirectoryCB->NameInformation.FileName,
1910 stIoResult.BytesProcessed);
1912 Irp->IoStatus.Information = stIoResult.BytesProcessed;
1919 AFSReleaseResource( &pFcb->NPFcb->Resource);
1922 if( pIoRequest != NULL)
1925 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);