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 bWriteToEndOfFile = FALSE;
125 BOOLEAN bWait = FALSE;
126 BOOLEAN bCompleteIrp = TRUE;
127 BOOLEAN bForceFlush = FALSE;
129 HANDLE hCallingUser = OnBehalfOf;
130 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
131 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
133 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
138 Irp->IoStatus.Information = 0;
140 pFileObject = pIrpSp->FileObject;
143 // Extract the fileobject references
146 pFcb = (AFSFcb *)pFileObject->FsContext;
147 pCcb = (AFSCcb *)pFileObject->FsContext2;
149 ObReferenceObject( pFileObject);
154 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
155 AFS_TRACE_LEVEL_ERROR,
156 "AFSCommonWrite Attempted write (%p) when pFcb == NULL\n",
159 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
162 pNPFcb = pFcb->NPFcb;
165 // If we are in shutdown mode then fail the request
168 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
171 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
172 AFS_TRACE_LEVEL_WARNING,
173 "AFSCommonWrite (%p) Open request after shutdown\n",
176 try_return( ntStatus = STATUS_TOO_LATE);
179 liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
180 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
181 bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
182 bWait = IoIsOperationSynchronous( Irp);
183 ulByteCount = pIrpSp->Parameters.Write.Length;
184 bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
186 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
187 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
188 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
191 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
192 AFS_TRACE_LEVEL_ERROR,
193 "AFSCommonWrite Attempted write (%p) on an invalid node type %08lX\n",
195 pFcb->Header.NodeTypeCode));
197 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
201 // If this is a write against an IOCtl node then handle it
202 // in a different pathway
205 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
208 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
209 AFS_TRACE_LEVEL_VERBOSE,
210 "AFSCommonWrite (%p) Processing file (PIOCTL) Offset %0I64X Length %08lX Irp Flags %08lX\n",
212 liStartingByte.QuadPart,
216 ntStatus = AFSIOCtlWrite( DeviceObject,
219 try_return( ntStatus);
221 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
224 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
225 AFS_TRACE_LEVEL_VERBOSE,
226 "AFSCommonWrite (%p) Processing file (SHARE) Offset %0I64X Length %08lX Irp Flags %08lX\n",
228 liStartingByte.QuadPart,
232 ntStatus = AFSShareWrite( DeviceObject,
235 try_return( ntStatus);
239 // Is the Cache not there yet? Exit.
241 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
242 !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
243 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
246 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
247 AFS_TRACE_LEVEL_ERROR,
248 "AFSCommonWrite (%p) Request failed due to AFS cache closed\n",
251 try_return( ntStatus = STATUS_TOO_LATE );
254 if( pFcb->ObjectInformation->VolumeCB != NULL &&
255 BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
258 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
259 AFS_TRACE_LEVEL_ERROR,
260 "AFSCommonWrite (%p) Request failed due to read only volume\n",
263 try_return( ntStatus = STATUS_ACCESS_DENIED);
267 // We need to know on whose behalf we have been called (which
268 // we will eventually tell to the server - for non paging
269 // writes). If we were posted then we were told. If this is
270 // the first time we saw the irp then we grab it now.
272 if( NULL == OnBehalfOf )
275 hCallingUser = PsGetCurrentProcessId();
280 hCallingUser = OnBehalfOf;
284 // Check for zero length write
287 if( ulByteCount == 0)
290 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
291 AFS_TRACE_LEVEL_VERBOSE,
292 "AFSCommonWrite (%p) Request completed due to zero length\n",
295 try_return( ntStatus);
299 // Is this Fcb valid???
302 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
305 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
306 AFS_TRACE_LEVEL_ERROR,
307 "AFSCommonWrite (%p) Failing request due to INVALID fcb\n",
310 try_return( ntStatus = STATUS_FILE_DELETED);
313 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
314 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
317 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
318 AFS_TRACE_LEVEL_ERROR,
319 "AFSCommonWrite (%p) Request failed due to file deleted\n",
322 try_return( ntStatus = STATUS_FILE_DELETED);
325 if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
328 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
329 AFS_TRACE_LEVEL_VERBOSE,
330 "AFSCommonWrite (%p) IRP_MN_COMPLETE being processed\n",
333 CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
336 // Mdl is now Deallocated
339 Irp->MdlAddress = NULL;
341 try_return( ntStatus = STATUS_SUCCESS );
345 // If we get a non cached IO for a cached file we should do a purge.
346 // For now we will just promote to cached
348 if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
350 bNonCachedIo = FALSE;
354 if ( !bNonCachedIo && !bPagingIo)
357 if( pFileObject->PrivateCacheMap == NULL)
360 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
361 AFS_TRACE_LEVEL_VERBOSE,
362 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
363 &pNPFcb->SectionObjectResource,
364 PsGetCurrentThread()));
366 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
369 bReleaseSectionObject = TRUE;
374 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
375 AFS_TRACE_LEVEL_VERBOSE,
376 "AFSCommonWrite Initialize caching on Fcb %p FileObject %p\n",
380 CcInitializeCacheMap( pFileObject,
381 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
383 AFSLibCacheManagerCallbacks,
386 CcSetReadAheadGranularity( pFileObject,
387 pDeviceExt->Specific.RDR.MaximumRPCLength);
389 CcSetDirtyPageThreshold( pFileObject,
390 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
392 __except( EXCEPTION_EXECUTE_HANDLER)
395 ntStatus = GetExceptionCode();
397 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
398 AFS_TRACE_LEVEL_ERROR,
399 "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
404 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
405 AFS_TRACE_LEVEL_VERBOSE,
406 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
407 &pNPFcb->SectionObjectResource,
408 PsGetCurrentThread()));
410 AFSReleaseResource( &pNPFcb->SectionObjectResource);
412 bReleaseSectionObject = FALSE;
414 if( !NT_SUCCESS( ntStatus))
417 try_return( ntStatus);
422 // On versions of Microsoft Windows older than Vista the IO Manager
423 // will issue multiple outstanding writes on a synchronous file object
424 // if one of the cached writes completes with STATUS_PENDING. This can
425 // result in the writes being completed out of order which can corrupt
426 // the end of file marker. On OS versions older than Vista use a spin
427 // loop instead of deferring the write.
430 if ( bSynchronousFo &&
431 AFSRtlSysVersion.dwMajorVersion < 6)
434 while (!CcCanIWrite( pFileObject,
439 static const LONGLONG llWriteDelay = (LONGLONG)-100000;
442 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
443 AFS_TRACE_LEVEL_WARNING,
444 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for %u bytes! Retry in 10ms\n",
448 KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
454 if (!CcCanIWrite( pFileObject,
460 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
461 AFS_TRACE_LEVEL_WARNING,
462 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
464 liStartingByte.QuadPart,
466 bRetry ? " RETRY" : ""));
468 ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
470 if ( STATUS_PENDING == ntStatus)
473 bCompleteIrp = FALSE;
478 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
479 AFS_TRACE_LEVEL_ERROR,
480 "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
485 try_return( ntStatus);
491 // Save off the PID if this is not a paging IO
495 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
496 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
497 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
500 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
502 if( ullProcessId == (ULONGLONG)AFSSysProcess)
504 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
505 AFS_TRACE_LEVEL_WARNING,
506 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
515 // - if Paging then we need to do nothing (the precalls will
516 // have acquired the paging resource), for clarity we will collect
517 // the paging resource
518 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
519 // - Otherwise we collect the file shared, check against extending and
530 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
532 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
533 AFS_TRACE_LEVEL_VERBOSE,
534 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
535 &pNPFcb->PagingResource,
536 PsGetCurrentThread()));
538 AFSAcquireShared( &pNPFcb->PagingResource,
541 bReleasePaging = TRUE;
544 // We have the correct lock - we cannot have the wrong one
551 bWriteToEndOfFile = liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
552 liStartingByte.HighPart == -1;
554 bExtendingWrite = ( bWriteToEndOfFile ||
555 ((liStartingByte.QuadPart + ulByteCount) >=
556 pFcb->Header.FileSize.QuadPart));
558 if( bExtendingWrite || bNonCachedIo)
561 // Check for lock inversion
565 // For bExtendingWrite the PagingResource is needed to protect
566 // the CcSetFileSizes call in AFSExtendingWrite
569 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
571 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
572 AFS_TRACE_LEVEL_VERBOSE,
573 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
575 PsGetCurrentThread()));
577 AFSAcquireExcl( &pNPFcb->Resource,
582 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
583 AFS_TRACE_LEVEL_VERBOSE,
584 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
585 &pNPFcb->SectionObjectResource,
586 PsGetCurrentThread()));
588 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
591 bReleaseSectionObject = TRUE;
593 if ( bWriteToEndOfFile)
596 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
599 liStartingByte = pFcb->Header.ValidDataLength;
604 liStartingByte = pFcb->Header.FileSize;
607 pIrpSp->Parameters.Write.ByteOffset = liStartingByte;
611 // We have the correct lock - even if we don't end up truncating
617 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
619 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
620 AFS_TRACE_LEVEL_VERBOSE,
621 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
623 PsGetCurrentThread()));
625 AFSAcquireShared( &pNPFcb->Resource,
630 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
631 AFS_TRACE_LEVEL_VERBOSE,
632 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
633 &pNPFcb->SectionObjectResource,
634 PsGetCurrentThread()));
636 AFSAcquireShared( &pNPFcb->SectionObjectResource,
639 bReleaseSectionObject = TRUE;
642 // Have things moved? Are we extending? If so, the the lock isn't OK
644 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
649 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
650 AFS_TRACE_LEVEL_VERBOSE,
651 "AFSCommonWrite Releasing Fcb SectionObject lock %p SHARED %08lX\n",
652 &pNPFcb->SectionObjectResource,
653 PsGetCurrentThread()));
655 AFSReleaseResource( &pNPFcb->SectionObjectResource);
657 bReleaseSectionObject = FALSE;
659 AFSReleaseResource( &pNPFcb->Resource);
661 bReleaseMain = FALSE;
672 // Check the BR locks on the file.
675 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
679 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
680 AFS_TRACE_LEVEL_ERROR,
681 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
684 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
690 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
693 // Fcb->NPFcb->Resource is now held SHARED
696 if( !NT_SUCCESS(ntStatus))
699 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
700 AFS_TRACE_LEVEL_ERROR,
701 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
705 try_return( ntStatus );
711 // Fire off the request as appropriate
713 bCompleteIrp = FALSE;
720 // Main resource held Shared
721 // SectionObject resource held exclusive if extending write
724 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
725 AFS_TRACE_LEVEL_VERBOSE,
726 "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
728 liStartingByte.QuadPart,
730 bRetry ? " RETRY" : ""));
732 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
737 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
738 AFS_TRACE_LEVEL_VERBOSE,
739 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
741 liStartingByte.QuadPart,
743 bRetry ? " RETRY" : ""));
745 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
748 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
752 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
758 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
759 AFS_TRACE_LEVEL_VERBOSE,
760 "AFSCommonWrite (%p) Process complete Status %08lX\n",
764 if ( NT_SUCCESS( ntStatus) &&
765 ntStatus != STATUS_PENDING)
773 pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
777 // If this extended the VDL, then update it accordingly.
778 // Increasing the VDL does not require a call to CcSetFileSizes.
781 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
784 pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
787 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
790 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
792 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
797 if ( ntStatus != STATUS_PENDING &&
798 !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
799 pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
800 bReleaseSectionObject)
803 // Regardless of whether or not the a non-paging non-cached write
804 // succeeds or fails, if the file is cached the contents of the
805 // cache are no longer up to date. A CcPurgeCacheSection must be
806 // performed to force subsequent cached reads to obtain the data
809 // The Fcb Resource is dropped in order to permit filters that perform
810 // an open via a worker thread in response to a purge to do so without
811 // deadlocking. The SectionObjectResource is held across the purge to
812 // prevent racing with other cache operations.
818 AFSReleaseResource( &pNPFcb->Resource);
820 bReleaseMain = FALSE;
826 if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
832 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
833 AFS_TRACE_LEVEL_WARNING,
834 "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
835 pFcb->ObjectInformation->FileId.Cell,
836 pFcb->ObjectInformation->FileId.Volume,
837 pFcb->ObjectInformation->FileId.Vnode,
838 pFcb->ObjectInformation->FileId.Unique));
840 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
843 __except( EXCEPTION_EXECUTE_HANDLER)
846 DWORD ntStatus2 = GetExceptionCode();
850 "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
851 pFcb->ObjectInformation->FileId.Cell,
852 pFcb->ObjectInformation->FileId.Volume,
853 pFcb->ObjectInformation->FileId.Vnode,
854 pFcb->ObjectInformation->FileId.Unique,
857 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
861 ObDereferenceObject(pFileObject);
863 if( bReleaseSectionObject)
866 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
867 AFS_TRACE_LEVEL_VERBOSE,
868 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
869 &pNPFcb->SectionObjectResource,
870 PsGetCurrentThread()));
872 AFSReleaseResource( &pNPFcb->SectionObjectResource);
878 AFSReleaseResource( &pNPFcb->PagingResource);
884 AFSReleaseResource( &pNPFcb->Resource);
890 AFSCompleteRequest( Irp,
899 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
903 UNREFERENCED_PARAMETER(DeviceObject);
904 NTSTATUS ntStatus = STATUS_SUCCESS;
905 AFSPIOCtlIORequestCB stIORequestCB;
906 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
909 AFSPIOCtlIOResultCB stIOResultCB;
910 ULONG ulBytesReturned = 0;
911 AFSFileID stParentFID;
916 Irp->IoStatus.Information = 0;
918 RtlZeroMemory( &stIORequestCB,
919 sizeof( AFSPIOCtlIORequestCB));
921 if( pIrpSp->Parameters.Write.Length == 0)
925 // Nothing to do in this case
928 try_return( ntStatus);
931 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
933 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
935 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
936 AFS_TRACE_LEVEL_VERBOSE,
937 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
938 &pFcb->NPFcb->Resource,
939 PsGetCurrentThread()));
941 AFSAcquireShared( &pFcb->NPFcb->Resource,
945 // Get the parent fid to pass to the cm
948 RtlZeroMemory( &stParentFID,
951 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
955 // The parent directory FID of the node
958 stParentFID = pFcb->ObjectInformation->ParentFileId;
962 // Set the control block up
965 stIORequestCB.RequestId = pCcb->RequestID;
967 if( pFcb->ObjectInformation->VolumeCB != NULL)
969 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
973 // Lock down the buffer
976 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
977 pIrpSp->Parameters.Write.Length);
979 if( stIORequestCB.MappedBuffer == NULL)
982 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
985 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
987 stIOResultCB.BytesProcessed = 0;
989 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
992 // Issue the request to the service
995 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
996 AFS_REQUEST_FLAG_SYNCHRONOUS,
1002 (void *)&stIORequestCB,
1003 sizeof( AFSPIOCtlIORequestCB),
1007 if( !NT_SUCCESS( ntStatus))
1010 try_return( ntStatus);
1014 // Update the length written
1017 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1021 if( stIORequestCB.MappedBuffer != NULL)
1024 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1031 AFSReleaseResource( &pFcb->NPFcb->Resource);
1039 // This function is called when we know we have to read from the AFS Cache.
1041 // It ensures that we have exents for the entirety of the write and
1042 // then pins the extents into memory (meaning that although we may
1043 // add we will not remove). Then it creates a scatter gather write
1044 // and fires off the IRPs
1048 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1050 IN LARGE_INTEGER StartingByte,
1053 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1054 VOID *pSystemBuffer = NULL;
1055 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1056 BOOLEAN bLocked = FALSE;
1057 BOOLEAN bCompleteIrp = TRUE;
1058 AFSGatherIo *pGatherIo = NULL;
1059 AFSIoRun *pIoRuns = NULL;
1060 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
1061 ULONG extentsCount = 0, runCount = 0;
1062 AFSExtent *pStartExtent = NULL;
1063 AFSExtent *pIgnoreExtent = NULL;
1064 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1065 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1066 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1067 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1068 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1069 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1070 LARGE_INTEGER liCurrentTime, liLastRequestTime;
1071 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1072 PFILE_OBJECT pCacheFileObject = NULL;
1073 BOOLEAN bDerefExtents = FALSE;
1078 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1079 AFS_TRACE_LEVEL_VERBOSE,
1080 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1082 StartingByte.HighPart,
1083 StartingByte.LowPart,
1086 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1089 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1090 AFS_TRACE_LEVEL_ERROR,
1091 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1094 pIrpSp->Parameters.Write.Length,
1095 pDevExt->Specific.RDR.MaxIo.QuadPart));
1097 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1101 // Get the mapping for the buffer
1103 pSystemBuffer = AFSLockSystemBuffer( Irp,
1106 if( pSystemBuffer == NULL)
1109 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1110 AFS_TRACE_LEVEL_ERROR,
1111 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
1114 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1119 // Provoke a get of the extents - if we need to.
1122 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1123 AFS_TRACE_LEVEL_VERBOSE,
1124 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1125 pFcb->ObjectInformation->FileId.Cell,
1126 pFcb->ObjectInformation->FileId.Volume,
1127 pFcb->ObjectInformation->FileId.Vnode,
1128 pFcb->ObjectInformation->FileId.Unique,
1129 StartingByte.QuadPart,
1132 ntStatus = AFSRequestExtentsAsync( pFcb,
1137 if (!NT_SUCCESS(ntStatus))
1140 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1141 AFS_TRACE_LEVEL_ERROR,
1142 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1146 try_return( ntStatus);
1149 KeQueryTickCount( &liLastRequestTime);
1154 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1155 AFS_TRACE_LEVEL_VERBOSE,
1156 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1157 &pFcb->NPFcb->Specific.File.ExtentsResource,
1158 PsGetCurrentThread()));
1160 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1162 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1165 pStartExtent = NULL;
1166 pIgnoreExtent = NULL;
1168 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1173 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1175 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1176 AFS_TRACE_LEVEL_VERBOSE,
1177 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1178 &pFcb->NPFcb->Specific.File.ExtentsResource,
1179 PsGetCurrentThread()));
1181 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1185 // We will re-request the extents after waiting for them
1188 KeQueryTickCount( &liCurrentTime);
1190 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1193 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1194 AFS_TRACE_LEVEL_VERBOSE,
1195 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1196 pFcb->ObjectInformation->FileId.Cell,
1197 pFcb->ObjectInformation->FileId.Volume,
1198 pFcb->ObjectInformation->FileId.Vnode,
1199 pFcb->ObjectInformation->FileId.Unique,
1200 StartingByte.QuadPart,
1203 ntStatus = AFSRequestExtentsAsync( pFcb,
1208 if (!NT_SUCCESS(ntStatus))
1211 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1212 AFS_TRACE_LEVEL_ERROR,
1213 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1217 try_return( ntStatus);
1220 KeQueryTickCount( &liLastRequestTime);
1224 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1225 AFS_TRACE_LEVEL_VERBOSE,
1226 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1227 pFcb->ObjectInformation->FileId.Cell,
1228 pFcb->ObjectInformation->FileId.Volume,
1229 pFcb->ObjectInformation->FileId.Vnode,
1230 pFcb->ObjectInformation->FileId.Unique,
1231 StartingByte.QuadPart,
1238 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1240 if (!NT_SUCCESS(ntStatus))
1243 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1244 AFS_TRACE_LEVEL_ERROR,
1245 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1246 pFcb->ObjectInformation->FileId.Cell,
1247 pFcb->ObjectInformation->FileId.Volume,
1248 pFcb->ObjectInformation->FileId.Vnode,
1249 pFcb->ObjectInformation->FileId.Unique,
1250 StartingByte.QuadPart,
1254 try_return( ntStatus);
1259 // As per the read path -
1262 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1263 AFS_TRACE_LEVEL_VERBOSE,
1264 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1265 pFcb->ObjectInformation->FileId.Cell,
1266 pFcb->ObjectInformation->FileId.Volume,
1267 pFcb->ObjectInformation->FileId.Vnode,
1268 pFcb->ObjectInformation->FileId.Unique,
1269 StartingByte.QuadPart,
1272 ntStatus = AFSGetExtents( pFcb,
1279 if (!NT_SUCCESS(ntStatus))
1282 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1283 AFS_TRACE_LEVEL_ERROR,
1284 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1288 try_return( ntStatus );
1291 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1292 AFS_TRACE_LEVEL_VERBOSE,
1293 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1298 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1301 Irp->IoStatus.Information = ByteCount;
1305 // Setup the MD5 for each extent
1308 AFSSetupMD5Hash( pFcb,
1316 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1322 if (!NT_SUCCESS(ntStatus))
1325 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1326 AFS_TRACE_LEVEL_ERROR,
1327 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1332 try_return( ntStatus);
1336 // Retrieve the cache file object
1339 pCacheFileObject = AFSReferenceCacheFileObject();
1341 if( pCacheFileObject == NULL)
1344 ntStatus = STATUS_DEVICE_NOT_READY;
1346 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1347 AFS_TRACE_LEVEL_ERROR,
1348 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1349 pFcb->ObjectInformation->FileId.Cell,
1350 pFcb->ObjectInformation->FileId.Volume,
1351 pFcb->ObjectInformation->FileId.Vnode,
1352 pFcb->ObjectInformation->FileId.Unique,
1353 StartingByte.QuadPart,
1357 try_return( ntStatus);
1360 if (runCount > AFS_MAX_STACK_IO_RUNS)
1363 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1364 runCount * sizeof( AFSIoRun ),
1366 if (NULL == pIoRuns)
1369 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1370 AFS_TRACE_LEVEL_ERROR,
1371 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1374 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1383 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1385 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1394 if (!NT_SUCCESS(ntStatus))
1397 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1398 AFS_TRACE_LEVEL_ERROR,
1399 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1403 try_return( ntStatus );
1406 AFSReferenceActiveExtents( pStartExtent,
1409 bDerefExtents = TRUE;
1411 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1412 AFS_TRACE_LEVEL_VERBOSE,
1413 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1414 &pFcb->NPFcb->Specific.File.ExtentsResource,
1415 PsGetCurrentThread()));
1417 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1420 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1421 sizeof( AFSGatherIo),
1424 if (NULL == pGatherIo)
1427 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1428 AFS_TRACE_LEVEL_ERROR,
1429 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1432 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1433 AFS_TRACE_LEVEL_VERBOSE,
1434 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1435 &pFcb->NPFcb->Specific.File.ExtentsResource,
1436 PsGetCurrentThread()));
1438 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1442 AFSDereferenceActiveExtents( pStartExtent,
1445 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1448 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1451 // Initialize count to 1, that was we won't get an early
1452 // completion if the first irp completes before the second is
1455 pGatherIo->Count = 1;
1456 pGatherIo->Status = STATUS_SUCCESS;
1457 pGatherIo->MasterIrp = Irp;
1458 pGatherIo->Synchronous = TRUE;
1459 pGatherIo->CompleteMasterIrp = FALSE;
1461 bCompleteIrp = TRUE;
1463 if( pGatherIo->Synchronous)
1465 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1470 // Setup the MD5 for each extent
1473 AFSSetupMD5Hash( pFcb,
1482 // Pre-emptively set up the count
1485 Irp->IoStatus.Information = ByteCount;
1487 ntStatus = AFSQueueStartIos( pCacheFileObject,
1489 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1494 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1495 AFS_TRACE_LEVEL_VERBOSE,
1496 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1500 if( !NT_SUCCESS( ntStatus))
1503 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1504 AFS_TRACE_LEVEL_VERBOSE,
1505 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1506 &pFcb->NPFcb->Specific.File.ExtentsResource,
1507 PsGetCurrentThread()));
1509 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1513 AFSDereferenceActiveExtents( pStartExtent,
1516 try_return( ntStatus);
1520 // Wait for completion of All IOs we started.
1523 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1529 if( NT_SUCCESS( ntStatus))
1532 ntStatus = pGatherIo->Status;
1535 if( !NT_SUCCESS( ntStatus))
1538 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1539 AFS_TRACE_LEVEL_VERBOSE,
1540 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1541 &pFcb->NPFcb->Specific.File.ExtentsResource,
1542 PsGetCurrentThread()));
1544 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1548 AFSDereferenceActiveExtents( pStartExtent,
1551 try_return( ntStatus);
1556 if( NT_SUCCESS( ntStatus) &&
1557 pStartExtent != NULL &&
1558 Irp->IoStatus.Information > 0)
1564 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1570 // Since this is dirty we can mark the extents dirty now.
1571 // AFSMarkDirty will dereference the extents. Do not call
1572 // AFSDereferenceActiveExtents() in this code path.
1584 // This was an uncached user write - tell the server to do
1585 // the flush when the worker thread next wakes up
1587 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1591 if( pCacheFileObject != NULL)
1593 AFSReleaseCacheFileObject( pCacheFileObject);
1596 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1597 AFS_TRACE_LEVEL_VERBOSE,
1598 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1600 StartingByte.HighPart,
1601 StartingByte.LowPart,
1605 if (NT_SUCCESS(ntStatus) &&
1610 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1616 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1617 AFS_TRACE_LEVEL_VERBOSE,
1618 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1619 &pFcb->NPFcb->Specific.File.ExtentsResource,
1620 PsGetCurrentThread()));
1622 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1627 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1630 if( NULL != pIoRuns &&
1631 stIoRuns != pIoRuns)
1633 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1639 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1640 AFS_TRACE_LEVEL_VERBOSE,
1641 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1644 Irp->IoStatus.Information));
1646 AFSCompleteRequest( Irp, ntStatus);
1655 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1657 IN LARGE_INTEGER StartingByte,
1660 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1661 VOID *pSystemBuffer = NULL;
1662 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1663 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1664 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1665 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1666 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1667 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1668 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1669 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1670 AFSFileIOCB stFileIORequest;
1671 AFSFileIOResultCB stFileIOResult;
1672 ULONG ulResultLen = 0;
1677 Irp->IoStatus.Information = 0;
1679 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1680 AFS_TRACE_LEVEL_VERBOSE,
1681 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1683 StartingByte.HighPart,
1684 StartingByte.LowPart,
1687 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1690 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1691 AFS_TRACE_LEVEL_ERROR,
1692 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1695 pIrpSp->Parameters.Write.Length,
1696 pDevExt->Specific.RDR.MaxIo.QuadPart));
1698 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1702 // Get the mapping for the buffer
1704 pSystemBuffer = AFSLockSystemBuffer( Irp,
1707 if( pSystemBuffer == NULL)
1710 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1711 AFS_TRACE_LEVEL_ERROR,
1712 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1715 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1719 // Issue the request at the service for processing
1722 ulResultLen = sizeof( AFSFileIOResultCB);
1724 RtlZeroMemory( &stFileIORequest,
1725 sizeof( AFSFileIOCB));
1727 RtlZeroMemory( &stFileIOResult,
1728 sizeof( AFSFileIOResultCB));
1730 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1732 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1734 stFileIORequest.IOLength = ByteCount;
1736 stFileIORequest.IOOffset = StartingByte;
1738 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1740 if ( bNoIntermediateBuffering)
1743 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1747 // Update file metadata
1750 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1752 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1754 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1756 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1758 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1761 // Write the data to the service
1764 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1767 &pCcb->DirectoryCB->NameInformation.FileName,
1768 &pFcb->ObjectInformation->FileId,
1769 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1770 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1772 sizeof( AFSFileIOCB),
1776 if( NT_SUCCESS( ntStatus))
1779 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1784 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1785 AFS_TRACE_LEVEL_ERROR,
1786 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1793 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1794 AFS_TRACE_LEVEL_VERBOSE,
1795 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1797 StartingByte.HighPart,
1798 StartingByte.LowPart,
1802 if (NT_SUCCESS(ntStatus) &&
1807 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1810 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1811 AFS_TRACE_LEVEL_VERBOSE,
1812 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1815 Irp->IoStatus.Information));
1817 AFSCompleteRequest( Irp, ntStatus);
1825 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1827 IN LARGE_INTEGER StartingByte,
1829 IN BOOLEAN ForceFlush)
1831 UNREFERENCED_PARAMETER(DeviceObject);
1832 PVOID pSystemBuffer = NULL;
1833 NTSTATUS ntStatus = STATUS_SUCCESS;
1834 IO_STATUS_BLOCK iosbFlush;
1835 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1836 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1837 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1838 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1839 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1840 PMDL pCurrentMdl = Irp->MdlAddress;
1841 LARGE_INTEGER liCurrentOffset;
1846 Irp->IoStatus.Information = 0;
1848 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1854 CcPrepareMdlWrite( pFileObject,
1860 ntStatus = Irp->IoStatus.Status;
1862 __except( EXCEPTION_EXECUTE_HANDLER)
1864 ntStatus = GetExceptionCode();
1866 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1867 AFS_TRACE_LEVEL_ERROR,
1868 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1873 if( !NT_SUCCESS( ntStatus))
1877 // Free up any potentially allocated mdl's
1880 CcMdlWriteComplete( pFileObject,
1884 Irp->MdlAddress = NULL;
1886 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1887 AFS_TRACE_LEVEL_ERROR,
1888 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1893 try_return( ntStatus);
1896 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1898 while( ulTotalLen > 0)
1901 ntStatus = STATUS_SUCCESS;
1903 if( pCurrentMdl != NULL)
1906 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1907 NormalPagePriority);
1909 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1911 if( ulCurrentIO > ulTotalLen)
1913 ulCurrentIO = ulTotalLen;
1919 pSystemBuffer = AFSLockSystemBuffer( Irp,
1922 ulCurrentIO = ulTotalLen;
1925 if( pSystemBuffer == NULL)
1928 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1929 AFS_TRACE_LEVEL_ERROR,
1930 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1933 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1939 if( !CcCopyWrite( pFileObject,
1946 // Failed to process request.
1949 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1950 AFS_TRACE_LEVEL_ERROR,
1951 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1953 &pFileObject->FileName,
1954 liCurrentOffset.QuadPart,
1955 Irp->IoStatus.Status));
1957 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1960 __except( EXCEPTION_EXECUTE_HANDLER)
1963 ntStatus = GetExceptionCode();
1965 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1966 AFS_TRACE_LEVEL_ERROR,
1967 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1969 &pFileObject->FileName,
1970 liCurrentOffset.QuadPart,
1974 if( !NT_SUCCESS( ntStatus))
1976 try_return( ntStatus);
1980 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1986 // We have detected a file we do a write through with.
1989 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1994 if( !NT_SUCCESS( iosbFlush.Status))
1997 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1998 AFS_TRACE_LEVEL_ERROR,
1999 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2001 &pFileObject->FileName,
2002 pFcb->ObjectInformation->FileId.Cell,
2003 pFcb->ObjectInformation->FileId.Volume,
2004 pFcb->ObjectInformation->FileId.Vnode,
2005 pFcb->ObjectInformation->FileId.Unique,
2007 iosbFlush.Information));
2009 try_return( ntStatus = iosbFlush.Status);
2012 __except( EXCEPTION_EXECUTE_HANDLER)
2015 ntStatus = GetExceptionCode();
2017 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2018 AFS_TRACE_LEVEL_ERROR,
2019 "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
2021 &pFileObject->FileName,
2022 liCurrentOffset.QuadPart,
2025 try_return( ntStatus);
2029 if( ulTotalLen <= ulCurrentIO)
2034 liCurrentOffset.QuadPart += ulCurrentIO;
2036 ulTotalLen -= ulCurrentIO;
2038 pCurrentMdl = pCurrentMdl->Next;
2043 if( NT_SUCCESS( ntStatus))
2046 Irp->IoStatus.Information = ByteCount;
2049 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
2052 // Write through asked for... Set things so that we get
2053 // flush when the worker thread next wakes up
2055 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
2059 AFSCompleteRequest( Irp,
2067 // Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
2072 AFSExtendingWrite( IN AFSFcb *Fcb,
2073 IN PFILE_OBJECT FileObject,
2074 IN LONGLONG NewLength)
2076 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
2077 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
2078 NTSTATUS ntStatus = STATUS_SUCCESS;
2079 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
2081 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
2084 Fcb->Header.AllocationSize.QuadPart = NewLength;
2086 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
2089 if( NewLength > Fcb->Header.FileSize.QuadPart)
2092 Fcb->Header.FileSize.QuadPart = NewLength;
2094 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
2101 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
2102 Fcb->ObjectInformation,
2105 if (NT_SUCCESS(ntStatus))
2108 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
2110 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2113 // If the file is currently cached, then let the MM know about the extension
2115 // The CcSetFileSizes call should be made with only the PagingResource held
2116 // which we are currently not holding.
2119 if( CcIsFileCached( FileObject))
2121 CcSetFileSizes( FileObject,
2122 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
2127 Fcb->Header.FileSize = liSaveFileSize;
2128 Fcb->Header.AllocationSize = liSaveAllocation;
2132 // DownConvert file resource to shared
2134 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2140 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2144 UNREFERENCED_PARAMETER(DeviceObject);
2145 NTSTATUS ntStatus = STATUS_SUCCESS;
2146 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2147 AFSFcb *pFcb = NULL;
2148 AFSCcb *pCcb = NULL;
2149 AFSPipeIORequestCB *pIoRequest = NULL;
2150 void *pBuffer = NULL;
2151 AFSPipeIOResultCB stIoResult;
2152 ULONG ulBytesReturned = 0;
2157 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2159 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2160 AFS_TRACE_LEVEL_VERBOSE,
2161 "AFSShareWrite On pipe %wZ Length %08lX\n",
2162 &pCcb->DirectoryCB->NameInformation.FileName,
2163 pIrpSp->Parameters.Write.Length));
2165 if( pIrpSp->Parameters.Write.Length == 0)
2169 // Nothing to do in this case
2172 try_return( ntStatus);
2176 // Retrieve the buffer for the read request
2179 pBuffer = AFSLockSystemBuffer( Irp,
2180 pIrpSp->Parameters.Write.Length);
2182 if( pBuffer == NULL)
2185 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2186 AFS_TRACE_LEVEL_ERROR,
2187 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2188 &pCcb->DirectoryCB->NameInformation.FileName));
2190 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2193 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2195 AFSAcquireShared( &pFcb->NPFcb->Resource,
2198 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2199 sizeof( AFSPipeIORequestCB) +
2200 pIrpSp->Parameters.Write.Length,
2201 AFS_GENERIC_MEMORY_14_TAG);
2203 if( pIoRequest == NULL)
2206 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2209 RtlZeroMemory( pIoRequest,
2210 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2212 pIoRequest->RequestId = pCcb->RequestID;
2214 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2216 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2218 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2220 pIrpSp->Parameters.Write.Length);
2222 stIoResult.BytesProcessed = 0;
2224 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2227 // Issue the open request to the service
2230 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2231 AFS_REQUEST_FLAG_SYNCHRONOUS,
2233 &pCcb->DirectoryCB->NameInformation.FileName,
2238 sizeof( AFSPipeIORequestCB) +
2239 pIrpSp->Parameters.Write.Length,
2243 if( !NT_SUCCESS( ntStatus))
2246 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2247 AFS_TRACE_LEVEL_ERROR,
2248 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2252 try_return( ntStatus);
2255 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2256 AFS_TRACE_LEVEL_VERBOSE,
2257 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2258 &pCcb->DirectoryCB->NameInformation.FileName,
2259 stIoResult.BytesProcessed));
2261 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2268 AFSReleaseResource( &pFcb->NPFcb->Resource);
2271 if( pIoRequest != NULL)
2274 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);