2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 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 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
59 IN LARGE_INTEGER StartingByte,
64 AFSExtendingWrite( IN AFSFcb *Fcb,
65 IN PFILE_OBJECT FileObject,
66 IN LONGLONG NewLength);
73 // This is the dispatch handler for the IRP_MJ_WRITE request
77 // A status is returned for the function
80 AFSWrite( IN PDEVICE_OBJECT LibDeviceObject,
84 UNREFERENCED_PARAMETER(LibDeviceObject);
85 NTSTATUS ntStatus = STATUS_SUCCESS;
90 ntStatus = AFSCommonWrite( AFSRDRDeviceObject, Irp, NULL, FALSE);
92 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
95 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
102 AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
104 IN HANDLE OnBehalfOf,
108 NTSTATUS ntStatus = STATUS_SUCCESS;
109 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
110 IO_STACK_LOCATION *pIrpSp;
113 AFSNonPagedFcb *pNPFcb = NULL;
114 ULONG ulByteCount = 0;
115 LARGE_INTEGER liStartingByte;
116 PFILE_OBJECT pFileObject;
117 BOOLEAN bPagingIo = FALSE;
118 BOOLEAN bNonCachedIo = FALSE;
119 BOOLEAN bReleaseMain = FALSE;
120 BOOLEAN bReleaseSectionObject = FALSE;
121 BOOLEAN bReleasePaging = FALSE;
122 BOOLEAN bExtendingWrite = FALSE;
123 BOOLEAN bSynchronousFo = FALSE;
124 BOOLEAN bWait = FALSE;
125 BOOLEAN bCompleteIrp = TRUE;
126 BOOLEAN bForceFlush = FALSE;
128 HANDLE hCallingUser = OnBehalfOf;
129 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
130 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
132 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
137 Irp->IoStatus.Information = 0;
139 pFileObject = pIrpSp->FileObject;
142 // Extract the fileobject references
145 pFcb = (AFSFcb *)pFileObject->FsContext;
146 pCcb = (AFSCcb *)pFileObject->FsContext2;
148 ObReferenceObject( pFileObject);
153 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
154 AFS_TRACE_LEVEL_ERROR,
155 "AFSCommonWrite Attempted write (%p) when pFcb == NULL\n",
158 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
161 pNPFcb = pFcb->NPFcb;
164 // If we are in shutdown mode then fail the request
167 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
170 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
171 AFS_TRACE_LEVEL_WARNING,
172 "AFSCommonWrite (%p) Open request after shutdown\n",
175 try_return( ntStatus = STATUS_TOO_LATE);
178 liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
179 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
180 bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
181 bWait = IoIsOperationSynchronous( Irp);
182 ulByteCount = pIrpSp->Parameters.Write.Length;
183 bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
185 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
186 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
187 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
190 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
191 AFS_TRACE_LEVEL_ERROR,
192 "AFSCommonWrite Attempted write (%p) on an invalid node type %08lX\n",
194 pFcb->Header.NodeTypeCode));
196 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
200 // If this is a write against an IOCtl node then handle it
201 // in a different pathway
204 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
207 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
208 AFS_TRACE_LEVEL_VERBOSE,
209 "AFSCommonWrite (%p) Processing file (PIOCTL) Offset %0I64X Length %08lX Irp Flags %08lX\n",
211 liStartingByte.QuadPart,
215 ntStatus = AFSIOCtlWrite( DeviceObject,
218 try_return( ntStatus);
220 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
223 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
224 AFS_TRACE_LEVEL_VERBOSE,
225 "AFSCommonWrite (%p) Processing file (SHARE) Offset %0I64X Length %08lX Irp Flags %08lX\n",
227 liStartingByte.QuadPart,
231 ntStatus = AFSShareWrite( DeviceObject,
234 try_return( ntStatus);
238 // Is the Cache not there yet? Exit.
240 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
241 !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
242 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
245 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
246 AFS_TRACE_LEVEL_ERROR,
247 "AFSCommonWrite (%p) Request failed due to AFS cache closed\n",
250 try_return( ntStatus = STATUS_TOO_LATE );
253 if( pFcb->ObjectInformation->VolumeCB != NULL &&
254 BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
257 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
258 AFS_TRACE_LEVEL_ERROR,
259 "AFSCommonWrite (%p) Request failed due to read only volume\n",
262 try_return( ntStatus = STATUS_ACCESS_DENIED);
266 // We need to know on whose behalf we have been called (which
267 // we will eventually tell to the server - for non paging
268 // writes). If we were posted then we were told. If this is
269 // the first time we saw the irp then we grab it now.
271 if( NULL == OnBehalfOf )
274 hCallingUser = PsGetCurrentProcessId();
279 hCallingUser = OnBehalfOf;
283 // Check for zero length write
286 if( ulByteCount == 0)
289 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
290 AFS_TRACE_LEVEL_VERBOSE,
291 "AFSCommonWrite (%p) Request completed due to zero length\n",
294 try_return( ntStatus);
298 // Is this Fcb valid???
301 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
304 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
305 AFS_TRACE_LEVEL_ERROR,
306 "AFSCommonWrite (%p) Failing request due to INVALID fcb\n",
309 try_return( ntStatus = STATUS_FILE_DELETED);
312 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
313 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
316 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
317 AFS_TRACE_LEVEL_ERROR,
318 "AFSCommonWrite (%p) Request failed due to file deleted\n",
321 try_return( ntStatus = STATUS_FILE_DELETED);
324 if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
327 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
328 AFS_TRACE_LEVEL_VERBOSE,
329 "AFSCommonWrite (%p) IRP_MN_COMPLETE being processed\n",
332 CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
335 // Mdl is now Deallocated
338 Irp->MdlAddress = NULL;
340 try_return( ntStatus = STATUS_SUCCESS );
344 // If we get a non cached IO for a cached file we should do a purge.
345 // For now we will just promote to cached
347 if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
349 bNonCachedIo = FALSE;
353 if ( !bNonCachedIo && !bPagingIo)
356 if( pFileObject->PrivateCacheMap == NULL)
359 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
360 AFS_TRACE_LEVEL_VERBOSE,
361 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
362 &pNPFcb->SectionObjectResource,
363 PsGetCurrentThread()));
365 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
368 bReleaseSectionObject = TRUE;
373 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
374 AFS_TRACE_LEVEL_VERBOSE,
375 "AFSCommonWrite Initialize caching on Fcb %p FileObject %p\n",
379 CcInitializeCacheMap( pFileObject,
380 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
382 AFSLibCacheManagerCallbacks,
385 CcSetReadAheadGranularity( pFileObject,
386 pDeviceExt->Specific.RDR.MaximumRPCLength);
388 CcSetDirtyPageThreshold( pFileObject,
389 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
391 __except( EXCEPTION_EXECUTE_HANDLER)
394 ntStatus = GetExceptionCode();
396 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
397 AFS_TRACE_LEVEL_ERROR,
398 "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
403 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
404 AFS_TRACE_LEVEL_VERBOSE,
405 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
406 &pNPFcb->SectionObjectResource,
407 PsGetCurrentThread()));
409 AFSReleaseResource( &pNPFcb->SectionObjectResource);
411 bReleaseSectionObject = FALSE;
413 if( !NT_SUCCESS( ntStatus))
416 try_return( ntStatus);
421 // On versions of Microsoft Windows older than Vista the IO Manager
422 // will issue multiple outstanding writes on a synchronous file object
423 // if one of the cached writes completes with STATUS_PENDING. This can
424 // result in the writes being completed out of order which can corrupt
425 // the end of file marker. On OS versions older than Vista use a spin
426 // loop instead of deferring the write.
429 if ( bSynchronousFo &&
430 AFSRtlSysVersion.dwMajorVersion < 6)
433 while (!CcCanIWrite( pFileObject,
438 static const LONGLONG llWriteDelay = (LONGLONG)-100000;
441 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
442 AFS_TRACE_LEVEL_WARNING,
443 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for %u bytes! Retry in 10ms\n",
447 KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
453 if (!CcCanIWrite( pFileObject,
459 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
460 AFS_TRACE_LEVEL_WARNING,
461 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
463 liStartingByte.QuadPart,
465 bRetry ? " RETRY" : ""));
467 ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
469 if ( STATUS_PENDING == ntStatus)
472 bCompleteIrp = FALSE;
477 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
478 AFS_TRACE_LEVEL_ERROR,
479 "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
484 try_return( ntStatus);
490 // Save off the PID if this is not a paging IO
494 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
495 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
496 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
499 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
501 if( ullProcessId == (ULONGLONG)AFSSysProcess)
503 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
504 AFS_TRACE_LEVEL_WARNING,
505 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
514 // - if Paging then we need to do nothing (the precalls will
515 // have acquired the paging resource), for clarity we will collect
516 // the paging resource
517 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
518 // - Otherwise we collect the file shared, check against extending and
529 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
531 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
532 AFS_TRACE_LEVEL_VERBOSE,
533 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
534 &pNPFcb->PagingResource,
535 PsGetCurrentThread()));
537 AFSAcquireShared( &pNPFcb->PagingResource,
540 bReleasePaging = TRUE;
543 // We have the correct lock - we cannot have the wrong one
550 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
551 pFcb->Header.FileSize.QuadPart) ||
552 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
553 liStartingByte.HighPart == -1)) ;
555 if( bExtendingWrite || bNonCachedIo)
558 // Check for lock inversion
562 // For bExtendingWrite the PagingResource is needed to protect
563 // the CcSetFileSizes call in AFSExtendingWrite
566 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
568 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
569 AFS_TRACE_LEVEL_VERBOSE,
570 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
572 PsGetCurrentThread()));
574 AFSAcquireExcl( &pNPFcb->Resource,
579 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
580 AFS_TRACE_LEVEL_VERBOSE,
581 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
582 &pNPFcb->SectionObjectResource,
583 PsGetCurrentThread()));
585 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
588 bReleaseSectionObject = TRUE;
590 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
591 liStartingByte.HighPart == -1)
593 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
595 liStartingByte = pFcb->Header.ValidDataLength;
599 liStartingByte = pFcb->Header.FileSize;
604 // We have the correct lock - even if we don't end up truncating
610 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
612 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
613 AFS_TRACE_LEVEL_VERBOSE,
614 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
616 PsGetCurrentThread()));
618 AFSAcquireShared( &pNPFcb->Resource,
623 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
624 AFS_TRACE_LEVEL_VERBOSE,
625 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
626 &pNPFcb->SectionObjectResource,
627 PsGetCurrentThread()));
629 AFSAcquireShared( &pNPFcb->SectionObjectResource,
632 bReleaseSectionObject = TRUE;
635 // Have things moved? Are we extending? If so, the the lock isn't OK
637 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
642 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
643 AFS_TRACE_LEVEL_VERBOSE,
644 "AFSCommonWrite Releasing Fcb SectionObject lock %p SHARED %08lX\n",
645 &pNPFcb->SectionObjectResource,
646 PsGetCurrentThread()));
648 AFSReleaseResource( &pNPFcb->SectionObjectResource);
650 bReleaseSectionObject = FALSE;
652 AFSReleaseResource( &pNPFcb->Resource);
654 bReleaseMain = FALSE;
665 // Check the BR locks on the file.
668 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
672 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
673 AFS_TRACE_LEVEL_ERROR,
674 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
677 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
683 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
686 // Fcb->NPFcb->Resource is now held SHARED
689 if( !NT_SUCCESS(ntStatus))
692 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
693 AFS_TRACE_LEVEL_ERROR,
694 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
698 try_return( ntStatus );
704 // Fire off the request as appropriate
706 bCompleteIrp = FALSE;
713 // Main resource held Shared
714 // SectionObject resource held exclusive if extending write
717 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
718 AFS_TRACE_LEVEL_VERBOSE,
719 "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
721 liStartingByte.QuadPart,
723 bRetry ? " RETRY" : ""));
725 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
730 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
731 AFS_TRACE_LEVEL_VERBOSE,
732 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
734 liStartingByte.QuadPart,
736 bRetry ? " RETRY" : ""));
738 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
741 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
745 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
751 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
752 AFS_TRACE_LEVEL_VERBOSE,
753 "AFSCommonWrite (%p) Process complete Status %08lX\n",
757 if ( NT_SUCCESS( ntStatus) &&
758 ntStatus != STATUS_PENDING)
766 pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
770 // If this extended the VDL, then update it accordingly.
771 // Increasing the VDL does not require a call to CcSetFileSizes.
774 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
777 pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
780 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
783 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
785 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
790 if ( ntStatus != STATUS_PENDING &&
791 !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
792 pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
793 bReleaseSectionObject)
796 // Regardless of whether or not the a non-paging non-cached write
797 // succeeds or fails, if the file is cached the contents of the
798 // cache are no longer up to date. A CcPurgeCacheSection must be
799 // performed to force subsequent cached reads to obtain the data
802 // The Fcb Resource is dropped in order to permit filters that perform
803 // an open via a worker thread in response to a purge to do so without
804 // deadlocking. The SectionObjectResource is held across the purge to
805 // prevent racing with other cache operations.
811 AFSReleaseResource( &pNPFcb->Resource);
813 bReleaseMain = FALSE;
819 if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
825 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
826 AFS_TRACE_LEVEL_WARNING,
827 "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
828 pFcb->ObjectInformation->FileId.Cell,
829 pFcb->ObjectInformation->FileId.Volume,
830 pFcb->ObjectInformation->FileId.Vnode,
831 pFcb->ObjectInformation->FileId.Unique));
833 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
836 __except( EXCEPTION_EXECUTE_HANDLER)
839 DWORD ntStatus2 = GetExceptionCode();
843 "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
844 pFcb->ObjectInformation->FileId.Cell,
845 pFcb->ObjectInformation->FileId.Volume,
846 pFcb->ObjectInformation->FileId.Vnode,
847 pFcb->ObjectInformation->FileId.Unique,
850 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
854 ObDereferenceObject(pFileObject);
856 if( bReleaseSectionObject)
859 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
860 AFS_TRACE_LEVEL_VERBOSE,
861 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
862 &pNPFcb->SectionObjectResource,
863 PsGetCurrentThread()));
865 AFSReleaseResource( &pNPFcb->SectionObjectResource);
871 AFSReleaseResource( &pNPFcb->PagingResource);
877 AFSReleaseResource( &pNPFcb->Resource);
883 AFSCompleteRequest( Irp,
892 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
896 UNREFERENCED_PARAMETER(DeviceObject);
897 NTSTATUS ntStatus = STATUS_SUCCESS;
898 AFSPIOCtlIORequestCB stIORequestCB;
899 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
902 AFSPIOCtlIOResultCB stIOResultCB;
903 ULONG ulBytesReturned = 0;
904 AFSFileID stParentFID;
909 Irp->IoStatus.Information = 0;
911 RtlZeroMemory( &stIORequestCB,
912 sizeof( AFSPIOCtlIORequestCB));
914 if( pIrpSp->Parameters.Write.Length == 0)
918 // Nothing to do in this case
921 try_return( ntStatus);
924 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
926 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
928 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
929 AFS_TRACE_LEVEL_VERBOSE,
930 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
931 &pFcb->NPFcb->Resource,
932 PsGetCurrentThread()));
934 AFSAcquireShared( &pFcb->NPFcb->Resource,
938 // Get the parent fid to pass to the cm
941 RtlZeroMemory( &stParentFID,
944 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
948 // The parent directory FID of the node
951 stParentFID = pFcb->ObjectInformation->ParentFileId;
955 // Set the control block up
958 stIORequestCB.RequestId = pCcb->RequestID;
960 if( pFcb->ObjectInformation->VolumeCB != NULL)
962 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
966 // Lock down the buffer
969 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
970 pIrpSp->Parameters.Write.Length);
972 if( stIORequestCB.MappedBuffer == NULL)
975 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
978 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
980 stIOResultCB.BytesProcessed = 0;
982 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
985 // Issue the request to the service
988 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
989 AFS_REQUEST_FLAG_SYNCHRONOUS,
995 (void *)&stIORequestCB,
996 sizeof( AFSPIOCtlIORequestCB),
1000 if( !NT_SUCCESS( ntStatus))
1003 try_return( ntStatus);
1007 // Update the length written
1010 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1014 if( stIORequestCB.MappedBuffer != NULL)
1017 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1024 AFSReleaseResource( &pFcb->NPFcb->Resource);
1032 // This function is called when we know we have to read from the AFS Cache.
1034 // It ensures that we have exents for the entirety of the write and
1035 // then pins the extents into memory (meaning that although we may
1036 // add we will not remove). Then it creates a scatter gather write
1037 // and fires off the IRPs
1041 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1043 IN LARGE_INTEGER StartingByte,
1046 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1047 VOID *pSystemBuffer = NULL;
1048 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1049 BOOLEAN bLocked = FALSE;
1050 BOOLEAN bCompleteIrp = TRUE;
1051 AFSGatherIo *pGatherIo = NULL;
1052 AFSIoRun *pIoRuns = NULL;
1053 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
1054 ULONG extentsCount = 0, runCount = 0;
1055 AFSExtent *pStartExtent = NULL;
1056 AFSExtent *pIgnoreExtent = NULL;
1057 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1058 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1059 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1060 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1061 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1062 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1063 LARGE_INTEGER liCurrentTime, liLastRequestTime;
1064 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1065 PFILE_OBJECT pCacheFileObject = NULL;
1066 BOOLEAN bDerefExtents = FALSE;
1071 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1072 AFS_TRACE_LEVEL_VERBOSE,
1073 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1075 StartingByte.HighPart,
1076 StartingByte.LowPart,
1079 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1082 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1083 AFS_TRACE_LEVEL_ERROR,
1084 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1087 pIrpSp->Parameters.Write.Length,
1088 pDevExt->Specific.RDR.MaxIo.QuadPart));
1090 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1094 // Get the mapping for the buffer
1096 pSystemBuffer = AFSLockSystemBuffer( Irp,
1099 if( pSystemBuffer == NULL)
1102 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1103 AFS_TRACE_LEVEL_ERROR,
1104 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
1107 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1112 // Provoke a get of the extents - if we need to.
1115 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1116 AFS_TRACE_LEVEL_VERBOSE,
1117 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1118 pFcb->ObjectInformation->FileId.Cell,
1119 pFcb->ObjectInformation->FileId.Volume,
1120 pFcb->ObjectInformation->FileId.Vnode,
1121 pFcb->ObjectInformation->FileId.Unique,
1122 StartingByte.QuadPart,
1125 ntStatus = AFSRequestExtentsAsync( pFcb,
1130 if (!NT_SUCCESS(ntStatus))
1133 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1134 AFS_TRACE_LEVEL_ERROR,
1135 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1139 try_return( ntStatus);
1142 KeQueryTickCount( &liLastRequestTime);
1147 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1148 AFS_TRACE_LEVEL_VERBOSE,
1149 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1150 &pFcb->NPFcb->Specific.File.ExtentsResource,
1151 PsGetCurrentThread()));
1153 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1155 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1158 pStartExtent = NULL;
1159 pIgnoreExtent = NULL;
1161 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1166 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1168 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1169 AFS_TRACE_LEVEL_VERBOSE,
1170 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1171 &pFcb->NPFcb->Specific.File.ExtentsResource,
1172 PsGetCurrentThread()));
1174 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1178 // We will re-request the extents after waiting for them
1181 KeQueryTickCount( &liCurrentTime);
1183 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1186 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1187 AFS_TRACE_LEVEL_VERBOSE,
1188 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1189 pFcb->ObjectInformation->FileId.Cell,
1190 pFcb->ObjectInformation->FileId.Volume,
1191 pFcb->ObjectInformation->FileId.Vnode,
1192 pFcb->ObjectInformation->FileId.Unique,
1193 StartingByte.QuadPart,
1196 ntStatus = AFSRequestExtentsAsync( pFcb,
1201 if (!NT_SUCCESS(ntStatus))
1204 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1205 AFS_TRACE_LEVEL_ERROR,
1206 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1210 try_return( ntStatus);
1213 KeQueryTickCount( &liLastRequestTime);
1217 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1218 AFS_TRACE_LEVEL_VERBOSE,
1219 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1220 pFcb->ObjectInformation->FileId.Cell,
1221 pFcb->ObjectInformation->FileId.Volume,
1222 pFcb->ObjectInformation->FileId.Vnode,
1223 pFcb->ObjectInformation->FileId.Unique,
1224 StartingByte.QuadPart,
1231 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1233 if (!NT_SUCCESS(ntStatus))
1236 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1237 AFS_TRACE_LEVEL_ERROR,
1238 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1239 pFcb->ObjectInformation->FileId.Cell,
1240 pFcb->ObjectInformation->FileId.Volume,
1241 pFcb->ObjectInformation->FileId.Vnode,
1242 pFcb->ObjectInformation->FileId.Unique,
1243 StartingByte.QuadPart,
1247 try_return( ntStatus);
1252 // As per the read path -
1255 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1256 AFS_TRACE_LEVEL_VERBOSE,
1257 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1258 pFcb->ObjectInformation->FileId.Cell,
1259 pFcb->ObjectInformation->FileId.Volume,
1260 pFcb->ObjectInformation->FileId.Vnode,
1261 pFcb->ObjectInformation->FileId.Unique,
1262 StartingByte.QuadPart,
1265 ntStatus = AFSGetExtents( pFcb,
1272 if (!NT_SUCCESS(ntStatus))
1275 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1276 AFS_TRACE_LEVEL_ERROR,
1277 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1281 try_return( ntStatus );
1284 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1285 AFS_TRACE_LEVEL_VERBOSE,
1286 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1291 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1294 Irp->IoStatus.Information = ByteCount;
1298 // Setup the MD5 for each extent
1301 AFSSetupMD5Hash( pFcb,
1309 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1315 if (!NT_SUCCESS(ntStatus))
1318 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1319 AFS_TRACE_LEVEL_ERROR,
1320 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1325 try_return( ntStatus);
1329 // Retrieve the cache file object
1332 pCacheFileObject = AFSReferenceCacheFileObject();
1334 if( pCacheFileObject == NULL)
1337 ntStatus = STATUS_DEVICE_NOT_READY;
1339 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1340 AFS_TRACE_LEVEL_ERROR,
1341 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1342 pFcb->ObjectInformation->FileId.Cell,
1343 pFcb->ObjectInformation->FileId.Volume,
1344 pFcb->ObjectInformation->FileId.Vnode,
1345 pFcb->ObjectInformation->FileId.Unique,
1346 StartingByte.QuadPart,
1350 try_return( ntStatus);
1353 if (runCount > AFS_MAX_STACK_IO_RUNS)
1356 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1357 runCount * sizeof( AFSIoRun ),
1359 if (NULL == pIoRuns)
1362 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1363 AFS_TRACE_LEVEL_ERROR,
1364 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1367 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1376 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1378 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1387 if (!NT_SUCCESS(ntStatus))
1390 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1391 AFS_TRACE_LEVEL_ERROR,
1392 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1396 try_return( ntStatus );
1399 AFSReferenceActiveExtents( pStartExtent,
1402 bDerefExtents = TRUE;
1404 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1405 AFS_TRACE_LEVEL_VERBOSE,
1406 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1407 &pFcb->NPFcb->Specific.File.ExtentsResource,
1408 PsGetCurrentThread()));
1410 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1413 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1414 sizeof( AFSGatherIo),
1417 if (NULL == pGatherIo)
1420 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1421 AFS_TRACE_LEVEL_ERROR,
1422 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1425 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1426 AFS_TRACE_LEVEL_VERBOSE,
1427 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1428 &pFcb->NPFcb->Specific.File.ExtentsResource,
1429 PsGetCurrentThread()));
1431 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1435 AFSDereferenceActiveExtents( pStartExtent,
1438 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1441 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1444 // Initialize count to 1, that was we won't get an early
1445 // completion if the first irp completes before the second is
1448 pGatherIo->Count = 1;
1449 pGatherIo->Status = STATUS_SUCCESS;
1450 pGatherIo->MasterIrp = Irp;
1451 pGatherIo->Synchronous = TRUE;
1452 pGatherIo->CompleteMasterIrp = FALSE;
1454 bCompleteIrp = TRUE;
1456 if( pGatherIo->Synchronous)
1458 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1463 // Setup the MD5 for each extent
1466 AFSSetupMD5Hash( pFcb,
1475 // Pre-emptively set up the count
1478 Irp->IoStatus.Information = ByteCount;
1480 ntStatus = AFSQueueStartIos( pCacheFileObject,
1482 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1487 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1488 AFS_TRACE_LEVEL_VERBOSE,
1489 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1493 if( !NT_SUCCESS( ntStatus))
1496 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1497 AFS_TRACE_LEVEL_VERBOSE,
1498 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1499 &pFcb->NPFcb->Specific.File.ExtentsResource,
1500 PsGetCurrentThread()));
1502 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1506 AFSDereferenceActiveExtents( pStartExtent,
1509 try_return( ntStatus);
1513 // Wait for completion of All IOs we started.
1516 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1522 if( NT_SUCCESS( ntStatus))
1525 ntStatus = pGatherIo->Status;
1528 if( !NT_SUCCESS( ntStatus))
1531 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1532 AFS_TRACE_LEVEL_VERBOSE,
1533 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1534 &pFcb->NPFcb->Specific.File.ExtentsResource,
1535 PsGetCurrentThread()));
1537 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1541 AFSDereferenceActiveExtents( pStartExtent,
1544 try_return( ntStatus);
1549 if( NT_SUCCESS( ntStatus) &&
1550 pStartExtent != NULL &&
1551 Irp->IoStatus.Information > 0)
1557 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1563 // Since this is dirty we can mark the extents dirty now.
1564 // AFSMarkDirty will dereference the extents. Do not call
1565 // AFSDereferenceActiveExtents() in this code path.
1577 // This was an uncached user write - tell the server to do
1578 // the flush when the worker thread next wakes up
1580 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1584 if( pCacheFileObject != NULL)
1586 AFSReleaseCacheFileObject( pCacheFileObject);
1589 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1590 AFS_TRACE_LEVEL_VERBOSE,
1591 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1593 StartingByte.HighPart,
1594 StartingByte.LowPart,
1598 if (NT_SUCCESS(ntStatus) &&
1603 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1609 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1610 AFS_TRACE_LEVEL_VERBOSE,
1611 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1612 &pFcb->NPFcb->Specific.File.ExtentsResource,
1613 PsGetCurrentThread()));
1615 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1620 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1623 if( NULL != pIoRuns &&
1624 stIoRuns != pIoRuns)
1626 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1632 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1633 AFS_TRACE_LEVEL_VERBOSE,
1634 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1637 Irp->IoStatus.Information));
1639 AFSCompleteRequest( Irp, ntStatus);
1648 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1650 IN LARGE_INTEGER StartingByte,
1653 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1654 VOID *pSystemBuffer = NULL;
1655 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1656 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1657 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1658 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1659 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1660 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1661 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1662 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1663 AFSFileIOCB stFileIORequest;
1664 AFSFileIOResultCB stFileIOResult;
1665 ULONG ulResultLen = 0;
1670 Irp->IoStatus.Information = 0;
1672 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1673 AFS_TRACE_LEVEL_VERBOSE,
1674 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1676 StartingByte.HighPart,
1677 StartingByte.LowPart,
1680 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1683 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1684 AFS_TRACE_LEVEL_ERROR,
1685 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1688 pIrpSp->Parameters.Write.Length,
1689 pDevExt->Specific.RDR.MaxIo.QuadPart));
1691 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1695 // Get the mapping for the buffer
1697 pSystemBuffer = AFSLockSystemBuffer( Irp,
1700 if( pSystemBuffer == NULL)
1703 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1704 AFS_TRACE_LEVEL_ERROR,
1705 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1708 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1712 // Issue the request at the service for processing
1715 ulResultLen = sizeof( AFSFileIOResultCB);
1717 RtlZeroMemory( &stFileIORequest,
1718 sizeof( AFSFileIOCB));
1720 RtlZeroMemory( &stFileIOResult,
1721 sizeof( AFSFileIOResultCB));
1723 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1725 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1727 stFileIORequest.IOLength = ByteCount;
1729 stFileIORequest.IOOffset = StartingByte;
1731 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1733 if ( bNoIntermediateBuffering)
1736 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1740 // Update file metadata
1743 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1745 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1747 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1749 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1751 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1754 // Write the data to the service
1757 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1760 &pCcb->DirectoryCB->NameInformation.FileName,
1761 &pFcb->ObjectInformation->FileId,
1762 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1763 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1765 sizeof( AFSFileIOCB),
1769 if( NT_SUCCESS( ntStatus))
1772 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1777 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1778 AFS_TRACE_LEVEL_ERROR,
1779 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1786 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1787 AFS_TRACE_LEVEL_VERBOSE,
1788 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1790 StartingByte.HighPart,
1791 StartingByte.LowPart,
1795 if (NT_SUCCESS(ntStatus) &&
1800 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1803 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1804 AFS_TRACE_LEVEL_VERBOSE,
1805 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1808 Irp->IoStatus.Information));
1810 AFSCompleteRequest( Irp, ntStatus);
1818 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1820 IN LARGE_INTEGER StartingByte,
1822 IN BOOLEAN ForceFlush)
1824 UNREFERENCED_PARAMETER(DeviceObject);
1825 PVOID pSystemBuffer = NULL;
1826 NTSTATUS ntStatus = STATUS_SUCCESS;
1827 IO_STATUS_BLOCK iosbFlush;
1828 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1829 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1830 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1831 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1832 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1833 PMDL pCurrentMdl = Irp->MdlAddress;
1834 LARGE_INTEGER liCurrentOffset;
1839 Irp->IoStatus.Information = 0;
1841 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1847 CcPrepareMdlWrite( pFileObject,
1853 ntStatus = Irp->IoStatus.Status;
1855 __except( EXCEPTION_EXECUTE_HANDLER)
1857 ntStatus = GetExceptionCode();
1859 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1860 AFS_TRACE_LEVEL_ERROR,
1861 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1866 if( !NT_SUCCESS( ntStatus))
1870 // Free up any potentially allocated mdl's
1873 CcMdlWriteComplete( pFileObject,
1877 Irp->MdlAddress = NULL;
1879 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1880 AFS_TRACE_LEVEL_ERROR,
1881 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1886 try_return( ntStatus);
1889 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1891 while( ulTotalLen > 0)
1894 ntStatus = STATUS_SUCCESS;
1896 if( pCurrentMdl != NULL)
1899 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1900 NormalPagePriority);
1902 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1904 if( ulCurrentIO > ulTotalLen)
1906 ulCurrentIO = ulTotalLen;
1912 pSystemBuffer = AFSLockSystemBuffer( Irp,
1915 ulCurrentIO = ulTotalLen;
1918 if( pSystemBuffer == NULL)
1921 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1922 AFS_TRACE_LEVEL_ERROR,
1923 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1926 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1932 if( !CcCopyWrite( pFileObject,
1939 // Failed to process request.
1942 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1943 AFS_TRACE_LEVEL_ERROR,
1944 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1946 &pFileObject->FileName,
1947 liCurrentOffset.QuadPart,
1948 Irp->IoStatus.Status));
1950 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1953 __except( EXCEPTION_EXECUTE_HANDLER)
1956 ntStatus = GetExceptionCode();
1958 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1959 AFS_TRACE_LEVEL_ERROR,
1960 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1962 &pFileObject->FileName,
1963 liCurrentOffset.QuadPart,
1967 if( !NT_SUCCESS( ntStatus))
1969 try_return( ntStatus);
1973 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1979 // We have detected a file we do a write through with.
1982 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1987 if( !NT_SUCCESS( iosbFlush.Status))
1990 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1991 AFS_TRACE_LEVEL_ERROR,
1992 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1994 &pFileObject->FileName,
1995 pFcb->ObjectInformation->FileId.Cell,
1996 pFcb->ObjectInformation->FileId.Volume,
1997 pFcb->ObjectInformation->FileId.Vnode,
1998 pFcb->ObjectInformation->FileId.Unique,
2000 iosbFlush.Information));
2002 try_return( ntStatus = iosbFlush.Status);
2005 __except( EXCEPTION_EXECUTE_HANDLER)
2008 ntStatus = GetExceptionCode();
2010 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2011 AFS_TRACE_LEVEL_ERROR,
2012 "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
2014 &pFileObject->FileName,
2015 liCurrentOffset.QuadPart,
2018 try_return( ntStatus);
2022 if( ulTotalLen <= ulCurrentIO)
2027 liCurrentOffset.QuadPart += ulCurrentIO;
2029 ulTotalLen -= ulCurrentIO;
2031 pCurrentMdl = pCurrentMdl->Next;
2036 if( NT_SUCCESS( ntStatus))
2039 Irp->IoStatus.Information = ByteCount;
2042 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
2045 // Write through asked for... Set things so that we get
2046 // flush when the worker thread next wakes up
2048 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
2052 AFSCompleteRequest( Irp,
2060 // Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
2065 AFSExtendingWrite( IN AFSFcb *Fcb,
2066 IN PFILE_OBJECT FileObject,
2067 IN LONGLONG NewLength)
2069 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
2070 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
2071 NTSTATUS ntStatus = STATUS_SUCCESS;
2072 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
2074 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
2077 Fcb->Header.AllocationSize.QuadPart = NewLength;
2079 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
2082 if( NewLength > Fcb->Header.FileSize.QuadPart)
2085 Fcb->Header.FileSize.QuadPart = NewLength;
2087 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
2094 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
2095 Fcb->ObjectInformation,
2098 if (NT_SUCCESS(ntStatus))
2101 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
2103 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2106 // If the file is currently cached, then let the MM know about the extension
2108 // The CcSetFileSizes call should be made with only the PagingResource held
2109 // which we are currently not holding.
2112 if( CcIsFileCached( FileObject))
2114 CcSetFileSizes( FileObject,
2115 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
2120 Fcb->Header.FileSize = liSaveFileSize;
2121 Fcb->Header.AllocationSize = liSaveAllocation;
2125 // DownConvert file resource to shared
2127 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2133 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2137 UNREFERENCED_PARAMETER(DeviceObject);
2138 NTSTATUS ntStatus = STATUS_SUCCESS;
2139 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2140 AFSFcb *pFcb = NULL;
2141 AFSCcb *pCcb = NULL;
2142 AFSPipeIORequestCB *pIoRequest = NULL;
2143 void *pBuffer = NULL;
2144 AFSPipeIOResultCB stIoResult;
2145 ULONG ulBytesReturned = 0;
2150 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2152 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2153 AFS_TRACE_LEVEL_VERBOSE,
2154 "AFSShareWrite On pipe %wZ Length %08lX\n",
2155 &pCcb->DirectoryCB->NameInformation.FileName,
2156 pIrpSp->Parameters.Write.Length));
2158 if( pIrpSp->Parameters.Write.Length == 0)
2162 // Nothing to do in this case
2165 try_return( ntStatus);
2169 // Retrieve the buffer for the read request
2172 pBuffer = AFSLockSystemBuffer( Irp,
2173 pIrpSp->Parameters.Write.Length);
2175 if( pBuffer == NULL)
2178 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2179 AFS_TRACE_LEVEL_ERROR,
2180 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2181 &pCcb->DirectoryCB->NameInformation.FileName));
2183 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2186 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2188 AFSAcquireShared( &pFcb->NPFcb->Resource,
2191 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2192 sizeof( AFSPipeIORequestCB) +
2193 pIrpSp->Parameters.Write.Length,
2194 AFS_GENERIC_MEMORY_14_TAG);
2196 if( pIoRequest == NULL)
2199 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2202 RtlZeroMemory( pIoRequest,
2203 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2205 pIoRequest->RequestId = pCcb->RequestID;
2207 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2209 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2211 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2213 pIrpSp->Parameters.Write.Length);
2215 stIoResult.BytesProcessed = 0;
2217 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2220 // Issue the open request to the service
2223 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2224 AFS_REQUEST_FLAG_SYNCHRONOUS,
2226 &pCcb->DirectoryCB->NameInformation.FileName,
2231 sizeof( AFSPipeIORequestCB) +
2232 pIrpSp->Parameters.Write.Length,
2236 if( !NT_SUCCESS( ntStatus))
2239 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2240 AFS_TRACE_LEVEL_ERROR,
2241 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2245 try_return( ntStatus);
2248 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2249 AFS_TRACE_LEVEL_VERBOSE,
2250 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2251 &pCcb->DirectoryCB->NameInformation.FileName,
2252 stIoResult.BytesProcessed));
2254 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2261 AFSReleaseResource( &pFcb->NPFcb->Resource);
2264 if( pIoRequest != NULL)
2267 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);