2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include "AFSCommon.h"
43 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
45 IN LARGE_INTEGER StartingByte,
47 IN BOOLEAN ForceFlush);
50 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
52 IN LARGE_INTEGER StartingByte,
57 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 bCompleteIrp = TRUE;
125 BOOLEAN bForceFlush = FALSE;
127 HANDLE hCallingUser = OnBehalfOf;
128 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
129 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
131 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
136 Irp->IoStatus.Information = 0;
138 pFileObject = pIrpSp->FileObject;
141 // Extract the fileobject references
144 pFcb = (AFSFcb *)pFileObject->FsContext;
145 pCcb = (AFSCcb *)pFileObject->FsContext2;
147 ObReferenceObject( pFileObject);
152 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
153 AFS_TRACE_LEVEL_ERROR,
154 "AFSCommonWrite Attempted write (%p) when pFcb == NULL\n",
157 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
160 pNPFcb = pFcb->NPFcb;
163 // If we are in shutdown mode then fail the request
166 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
169 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
170 AFS_TRACE_LEVEL_WARNING,
171 "AFSCommonWrite (%p) Open request after shutdown\n",
174 try_return( ntStatus = STATUS_TOO_LATE);
177 liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
178 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
179 bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
180 ulByteCount = pIrpSp->Parameters.Write.Length;
181 bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
183 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
184 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
185 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
188 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
189 AFS_TRACE_LEVEL_ERROR,
190 "AFSCommonWrite Attempted write (%p) on an invalid node type %08lX\n",
192 pFcb->Header.NodeTypeCode));
194 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
198 // If this is a write against an IOCtl node then handle it
199 // in a different pathway
202 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
205 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
206 AFS_TRACE_LEVEL_VERBOSE,
207 "AFSCommonWrite (%p) Processing file (PIOCTL) Offset %0I64X Length %08lX Irp Flags %08lX\n",
209 liStartingByte.QuadPart,
213 ntStatus = AFSIOCtlWrite( DeviceObject,
216 try_return( ntStatus);
218 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
221 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
222 AFS_TRACE_LEVEL_VERBOSE,
223 "AFSCommonWrite (%p) Processing file (SHARE) Offset %0I64X Length %08lX Irp Flags %08lX\n",
225 liStartingByte.QuadPart,
229 ntStatus = AFSShareWrite( DeviceObject,
232 try_return( ntStatus);
236 // Is the Cache not there yet? Exit.
238 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
239 !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
240 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
243 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
244 AFS_TRACE_LEVEL_ERROR,
245 "AFSCommonWrite (%p) Request failed due to AFS cache closed\n",
248 try_return( ntStatus = STATUS_TOO_LATE );
251 if( pFcb->ObjectInformation->VolumeCB != NULL &&
252 BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
255 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
256 AFS_TRACE_LEVEL_ERROR,
257 "AFSCommonWrite (%p) Request failed due to read only volume\n",
260 try_return( ntStatus = STATUS_ACCESS_DENIED);
264 // We need to know on whose behalf we have been called (which
265 // we will eventually tell to the server - for non paging
266 // writes). If we were posted then we were told. If this is
267 // the first time we saw the irp then we grab it now.
269 if( NULL == OnBehalfOf )
272 hCallingUser = PsGetCurrentProcessId();
277 hCallingUser = OnBehalfOf;
281 // Check for zero length write
284 if( ulByteCount == 0)
287 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
288 AFS_TRACE_LEVEL_VERBOSE,
289 "AFSCommonWrite (%p) Request completed due to zero length\n",
292 try_return( ntStatus);
296 // Is this Fcb valid???
299 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
302 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
303 AFS_TRACE_LEVEL_ERROR,
304 "AFSCommonWrite (%p) Failing request due to INVALID fcb\n",
307 try_return( ntStatus = STATUS_FILE_DELETED);
310 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
311 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
314 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
315 AFS_TRACE_LEVEL_ERROR,
316 "AFSCommonWrite (%p) Request failed due to file deleted\n",
319 try_return( ntStatus = STATUS_FILE_DELETED);
322 if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
325 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
326 AFS_TRACE_LEVEL_VERBOSE,
327 "AFSCommonWrite (%p) IRP_MN_COMPLETE being processed\n",
330 CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
333 // Mdl is now Deallocated
336 Irp->MdlAddress = NULL;
338 try_return( ntStatus = STATUS_SUCCESS );
342 // If we get a non cached IO for a cached file we should do a purge.
343 // For now we will just promote to cached
345 if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
347 bNonCachedIo = FALSE;
351 if ( !bNonCachedIo && !bPagingIo)
354 if( pFileObject->PrivateCacheMap == NULL)
357 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
358 AFS_TRACE_LEVEL_VERBOSE,
359 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
360 &pNPFcb->SectionObjectResource,
361 PsGetCurrentThread()));
363 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
366 bReleaseSectionObject = TRUE;
371 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
372 AFS_TRACE_LEVEL_VERBOSE,
373 "AFSCommonWrite Initialize caching on Fcb %p FileObject %p\n",
377 CcInitializeCacheMap( pFileObject,
378 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
380 AFSLibCacheManagerCallbacks,
383 CcSetReadAheadGranularity( pFileObject,
384 pDeviceExt->Specific.RDR.MaximumRPCLength);
386 CcSetDirtyPageThreshold( pFileObject,
387 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
389 __except( EXCEPTION_EXECUTE_HANDLER)
392 ntStatus = GetExceptionCode();
394 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
395 AFS_TRACE_LEVEL_ERROR,
396 "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
401 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
402 AFS_TRACE_LEVEL_VERBOSE,
403 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
404 &pNPFcb->SectionObjectResource,
405 PsGetCurrentThread()));
407 AFSReleaseResource( &pNPFcb->SectionObjectResource);
409 bReleaseSectionObject = FALSE;
411 if( !NT_SUCCESS( ntStatus))
414 try_return( ntStatus);
419 // On versions of Microsoft Windows older than Vista the IO Manager
420 // will issue multiple outstanding writes on a synchronous file object
421 // if one of the cached writes completes with STATUS_PENDING. This can
422 // result in the writes being completed out of order which can corrupt
423 // the end of file marker. On OS versions older than Vista use a spin
424 // loop instead of deferring the write.
427 if ( bSynchronousFo &&
428 AFSRtlSysVersion.dwMajorVersion < 6)
431 while (!CcCanIWrite( pFileObject,
436 static const LONGLONG llWriteDelay = (LONGLONG)-100000;
439 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
440 AFS_TRACE_LEVEL_WARNING,
441 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for %u bytes! Retry in 10ms\n",
445 KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
451 if (!CcCanIWrite( pFileObject,
457 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
458 AFS_TRACE_LEVEL_WARNING,
459 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
461 liStartingByte.QuadPart,
463 bRetry ? " RETRY" : ""));
465 ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
467 if ( STATUS_PENDING == ntStatus)
470 bCompleteIrp = FALSE;
475 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
476 AFS_TRACE_LEVEL_ERROR,
477 "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
482 try_return( ntStatus);
488 // Save off the PID if this is not a paging IO
492 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
493 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
494 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
497 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
499 if( ullProcessId == (ULONGLONG)AFSSysProcess)
501 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
502 AFS_TRACE_LEVEL_WARNING,
503 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
512 // - if Paging then we need to do nothing (the precalls will
513 // have acquired the paging resource), for clarity we will collect
514 // the paging resource
515 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
516 // - Otherwise we collect the file shared, check against extending and
527 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
529 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
530 AFS_TRACE_LEVEL_VERBOSE,
531 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
532 &pNPFcb->PagingResource,
533 PsGetCurrentThread()));
535 AFSAcquireShared( &pNPFcb->PagingResource,
538 bReleasePaging = TRUE;
541 // We have the correct lock - we cannot have the wrong one
548 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
549 pFcb->Header.FileSize.QuadPart) ||
550 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
551 liStartingByte.HighPart == -1)) ;
553 if( bExtendingWrite || bNonCachedIo)
556 // Check for lock inversion
560 // For bExtendingWrite the PagingResource is needed to protect
561 // the CcSetFileSizes call in AFSExtendingWrite
564 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
566 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
567 AFS_TRACE_LEVEL_VERBOSE,
568 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
570 PsGetCurrentThread()));
572 AFSAcquireExcl( &pNPFcb->Resource,
577 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
578 AFS_TRACE_LEVEL_VERBOSE,
579 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
580 &pNPFcb->SectionObjectResource,
581 PsGetCurrentThread()));
583 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
586 bReleaseSectionObject = TRUE;
588 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
589 liStartingByte.HighPart == -1)
591 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
593 liStartingByte = pFcb->Header.ValidDataLength;
597 liStartingByte = pFcb->Header.FileSize;
602 // We have the correct lock - even if we don't end up truncating
608 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
610 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
611 AFS_TRACE_LEVEL_VERBOSE,
612 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
614 PsGetCurrentThread()));
616 AFSAcquireShared( &pNPFcb->Resource,
621 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
622 AFS_TRACE_LEVEL_VERBOSE,
623 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
624 &pNPFcb->SectionObjectResource,
625 PsGetCurrentThread()));
627 AFSAcquireShared( &pNPFcb->SectionObjectResource,
630 bReleaseSectionObject = TRUE;
633 // Have things moved? Are we extending? If so, the the lock isn't OK
635 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
640 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
641 AFS_TRACE_LEVEL_VERBOSE,
642 "AFSCommonWrite Releasing Fcb SectionObject lock %p SHARED %08lX\n",
643 &pNPFcb->SectionObjectResource,
644 PsGetCurrentThread()));
646 AFSReleaseResource( &pNPFcb->SectionObjectResource);
648 bReleaseSectionObject = FALSE;
650 AFSReleaseResource( &pNPFcb->Resource);
652 bReleaseMain = FALSE;
663 // Check the BR locks on the file.
666 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
670 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
671 AFS_TRACE_LEVEL_ERROR,
672 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
675 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
681 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
684 // Fcb->NPFcb->Resource is now held SHARED
687 if( !NT_SUCCESS(ntStatus))
690 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
691 AFS_TRACE_LEVEL_ERROR,
692 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
696 try_return( ntStatus );
702 // Fire off the request as appropriate
704 bCompleteIrp = FALSE;
711 // Main resource held Shared
712 // SectionObject resource held exclusive if extending write
715 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
716 AFS_TRACE_LEVEL_VERBOSE,
717 "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
719 liStartingByte.QuadPart,
721 bRetry ? " RETRY" : ""));
723 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
728 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
729 AFS_TRACE_LEVEL_VERBOSE,
730 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
732 liStartingByte.QuadPart,
734 bRetry ? " RETRY" : ""));
736 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
739 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
743 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
749 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
750 AFS_TRACE_LEVEL_VERBOSE,
751 "AFSCommonWrite (%p) Process complete Status %08lX\n",
755 if ( NT_SUCCESS( ntStatus) &&
756 ntStatus != STATUS_PENDING)
764 pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
768 // If this extended the VDL, then update it accordingly.
769 // Increasing the VDL does not require a call to CcSetFileSizes.
772 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
775 pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
778 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
781 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
783 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
788 if ( ntStatus != STATUS_PENDING &&
789 !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
790 pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
791 bReleaseSectionObject)
794 // Regardless of whether or not the a non-paging non-cached write
795 // succeeds or fails, if the file is cached the contents of the
796 // cache are no longer up to date. A CcPurgeCacheSection must be
797 // performed to force subsequent cached reads to obtain the data
800 // The Fcb Resource is dropped in order to permit filters that perform
801 // an open via a worker thread in response to a purge to do so without
802 // deadlocking. The SectionObjectResource is held across the purge to
803 // prevent racing with other cache operations.
809 AFSReleaseResource( &pNPFcb->Resource);
811 bReleaseMain = FALSE;
817 if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
823 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
824 AFS_TRACE_LEVEL_WARNING,
825 "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
826 pFcb->ObjectInformation->FileId.Cell,
827 pFcb->ObjectInformation->FileId.Volume,
828 pFcb->ObjectInformation->FileId.Vnode,
829 pFcb->ObjectInformation->FileId.Unique));
831 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
834 __except( EXCEPTION_EXECUTE_HANDLER)
837 DWORD ntStatus2 = GetExceptionCode();
841 "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
842 pFcb->ObjectInformation->FileId.Cell,
843 pFcb->ObjectInformation->FileId.Volume,
844 pFcb->ObjectInformation->FileId.Vnode,
845 pFcb->ObjectInformation->FileId.Unique,
848 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
852 ObDereferenceObject(pFileObject);
854 if( bReleaseSectionObject)
857 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
858 AFS_TRACE_LEVEL_VERBOSE,
859 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
860 &pNPFcb->SectionObjectResource,
861 PsGetCurrentThread()));
863 AFSReleaseResource( &pNPFcb->SectionObjectResource);
869 AFSReleaseResource( &pNPFcb->PagingResource);
875 AFSReleaseResource( &pNPFcb->Resource);
881 AFSCompleteRequest( Irp,
890 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
894 UNREFERENCED_PARAMETER(DeviceObject);
895 NTSTATUS ntStatus = STATUS_SUCCESS;
896 AFSPIOCtlIORequestCB stIORequestCB;
897 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
900 AFSPIOCtlIOResultCB stIOResultCB;
901 ULONG ulBytesReturned = 0;
902 AFSFileID stParentFID;
907 Irp->IoStatus.Information = 0;
909 RtlZeroMemory( &stIORequestCB,
910 sizeof( AFSPIOCtlIORequestCB));
912 if( pIrpSp->Parameters.Write.Length == 0)
916 // Nothing to do in this case
919 try_return( ntStatus);
922 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
924 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
926 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
927 AFS_TRACE_LEVEL_VERBOSE,
928 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
929 &pFcb->NPFcb->Resource,
930 PsGetCurrentThread()));
932 AFSAcquireShared( &pFcb->NPFcb->Resource,
936 // Get the parent fid to pass to the cm
939 RtlZeroMemory( &stParentFID,
942 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
946 // The parent directory FID of the node
949 stParentFID = pFcb->ObjectInformation->ParentFileId;
953 // Set the control block up
956 stIORequestCB.RequestId = pCcb->RequestID;
958 if( pFcb->ObjectInformation->VolumeCB != NULL)
960 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
964 // Lock down the buffer
967 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
968 pIrpSp->Parameters.Write.Length);
970 if( stIORequestCB.MappedBuffer == NULL)
973 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
976 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
978 stIOResultCB.BytesProcessed = 0;
980 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
983 // Issue the request to the service
986 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
987 AFS_REQUEST_FLAG_SYNCHRONOUS,
993 (void *)&stIORequestCB,
994 sizeof( AFSPIOCtlIORequestCB),
998 if( !NT_SUCCESS( ntStatus))
1001 try_return( ntStatus);
1005 // Update the length written
1008 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1012 if( stIORequestCB.MappedBuffer != NULL)
1015 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1022 AFSReleaseResource( &pFcb->NPFcb->Resource);
1030 // This function is called when we know we have to read from the AFS Cache.
1032 // It ensures that we have exents for the entirety of the write and
1033 // then pins the extents into memory (meaning that although we may
1034 // add we will not remove). Then it creates a scatter gather write
1035 // and fires off the IRPs
1039 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1041 IN LARGE_INTEGER StartingByte,
1044 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1045 VOID *pSystemBuffer = NULL;
1046 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1047 BOOLEAN bLocked = FALSE;
1048 BOOLEAN bCompleteIrp = TRUE;
1049 AFSGatherIo *pGatherIo = NULL;
1050 AFSIoRun *pIoRuns = NULL;
1051 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
1052 ULONG extentsCount = 0, runCount = 0;
1053 AFSExtent *pStartExtent = NULL;
1054 AFSExtent *pIgnoreExtent = NULL;
1055 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1056 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1057 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1058 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1059 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1060 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1061 LARGE_INTEGER liCurrentTime, liLastRequestTime;
1062 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1063 PFILE_OBJECT pCacheFileObject = NULL;
1064 BOOLEAN bDerefExtents = FALSE;
1069 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1070 AFS_TRACE_LEVEL_VERBOSE,
1071 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1073 StartingByte.HighPart,
1074 StartingByte.LowPart,
1077 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1080 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1081 AFS_TRACE_LEVEL_ERROR,
1082 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1085 pIrpSp->Parameters.Write.Length,
1086 pDevExt->Specific.RDR.MaxIo.QuadPart));
1088 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1092 // Get the mapping for the buffer
1094 pSystemBuffer = AFSLockSystemBuffer( Irp,
1097 if( pSystemBuffer == NULL)
1100 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1101 AFS_TRACE_LEVEL_ERROR,
1102 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
1105 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1110 // Provoke a get of the extents - if we need to.
1113 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1114 AFS_TRACE_LEVEL_VERBOSE,
1115 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1116 pFcb->ObjectInformation->FileId.Cell,
1117 pFcb->ObjectInformation->FileId.Volume,
1118 pFcb->ObjectInformation->FileId.Vnode,
1119 pFcb->ObjectInformation->FileId.Unique,
1120 StartingByte.QuadPart,
1123 ntStatus = AFSRequestExtentsAsync( pFcb,
1128 if (!NT_SUCCESS(ntStatus))
1131 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1132 AFS_TRACE_LEVEL_ERROR,
1133 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1137 try_return( ntStatus);
1140 KeQueryTickCount( &liLastRequestTime);
1145 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1146 AFS_TRACE_LEVEL_VERBOSE,
1147 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1148 &pFcb->NPFcb->Specific.File.ExtentsResource,
1149 PsGetCurrentThread()));
1151 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1153 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1156 pStartExtent = NULL;
1157 pIgnoreExtent = NULL;
1159 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1164 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1166 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1167 AFS_TRACE_LEVEL_VERBOSE,
1168 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1169 &pFcb->NPFcb->Specific.File.ExtentsResource,
1170 PsGetCurrentThread()));
1172 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1176 // We will re-request the extents after waiting for them
1179 KeQueryTickCount( &liCurrentTime);
1181 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1184 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1185 AFS_TRACE_LEVEL_VERBOSE,
1186 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1187 pFcb->ObjectInformation->FileId.Cell,
1188 pFcb->ObjectInformation->FileId.Volume,
1189 pFcb->ObjectInformation->FileId.Vnode,
1190 pFcb->ObjectInformation->FileId.Unique,
1191 StartingByte.QuadPart,
1194 ntStatus = AFSRequestExtentsAsync( pFcb,
1199 if (!NT_SUCCESS(ntStatus))
1202 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1203 AFS_TRACE_LEVEL_ERROR,
1204 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1208 try_return( ntStatus);
1211 KeQueryTickCount( &liLastRequestTime);
1215 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1216 AFS_TRACE_LEVEL_VERBOSE,
1217 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1218 pFcb->ObjectInformation->FileId.Cell,
1219 pFcb->ObjectInformation->FileId.Volume,
1220 pFcb->ObjectInformation->FileId.Vnode,
1221 pFcb->ObjectInformation->FileId.Unique,
1222 StartingByte.QuadPart,
1229 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1231 if (!NT_SUCCESS(ntStatus))
1234 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1235 AFS_TRACE_LEVEL_ERROR,
1236 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1237 pFcb->ObjectInformation->FileId.Cell,
1238 pFcb->ObjectInformation->FileId.Volume,
1239 pFcb->ObjectInformation->FileId.Vnode,
1240 pFcb->ObjectInformation->FileId.Unique,
1241 StartingByte.QuadPart,
1245 try_return( ntStatus);
1250 // As per the read path -
1253 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1254 AFS_TRACE_LEVEL_VERBOSE,
1255 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1256 pFcb->ObjectInformation->FileId.Cell,
1257 pFcb->ObjectInformation->FileId.Volume,
1258 pFcb->ObjectInformation->FileId.Vnode,
1259 pFcb->ObjectInformation->FileId.Unique,
1260 StartingByte.QuadPart,
1263 ntStatus = AFSGetExtents( pFcb,
1270 if (!NT_SUCCESS(ntStatus))
1273 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1274 AFS_TRACE_LEVEL_ERROR,
1275 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1279 try_return( ntStatus );
1282 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1283 AFS_TRACE_LEVEL_VERBOSE,
1284 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1289 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1292 Irp->IoStatus.Information = ByteCount;
1296 // Setup the MD5 for each extent
1299 AFSSetupMD5Hash( pFcb,
1307 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1313 if (!NT_SUCCESS(ntStatus))
1316 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1317 AFS_TRACE_LEVEL_ERROR,
1318 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1323 try_return( ntStatus);
1327 // Retrieve the cache file object
1330 pCacheFileObject = AFSReferenceCacheFileObject();
1332 if( pCacheFileObject == NULL)
1335 ntStatus = STATUS_DEVICE_NOT_READY;
1337 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1338 AFS_TRACE_LEVEL_ERROR,
1339 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1340 pFcb->ObjectInformation->FileId.Cell,
1341 pFcb->ObjectInformation->FileId.Volume,
1342 pFcb->ObjectInformation->FileId.Vnode,
1343 pFcb->ObjectInformation->FileId.Unique,
1344 StartingByte.QuadPart,
1348 try_return( ntStatus);
1351 if (runCount > AFS_MAX_STACK_IO_RUNS)
1354 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1355 runCount * sizeof( AFSIoRun ),
1357 if (NULL == pIoRuns)
1360 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1361 AFS_TRACE_LEVEL_ERROR,
1362 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1365 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1374 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1376 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1385 if (!NT_SUCCESS(ntStatus))
1388 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1389 AFS_TRACE_LEVEL_ERROR,
1390 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1394 try_return( ntStatus );
1397 AFSReferenceActiveExtents( pStartExtent,
1400 bDerefExtents = TRUE;
1402 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1403 AFS_TRACE_LEVEL_VERBOSE,
1404 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1405 &pFcb->NPFcb->Specific.File.ExtentsResource,
1406 PsGetCurrentThread()));
1408 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1411 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1412 sizeof( AFSGatherIo),
1415 if (NULL == pGatherIo)
1418 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1419 AFS_TRACE_LEVEL_ERROR,
1420 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1423 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1424 AFS_TRACE_LEVEL_VERBOSE,
1425 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1426 &pFcb->NPFcb->Specific.File.ExtentsResource,
1427 PsGetCurrentThread()));
1429 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1433 AFSDereferenceActiveExtents( pStartExtent,
1436 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1439 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1442 // Initialize count to 1, that was we won't get an early
1443 // completion if the first irp completes before the second is
1446 pGatherIo->Count = 1;
1447 pGatherIo->Status = STATUS_SUCCESS;
1448 pGatherIo->MasterIrp = Irp;
1449 pGatherIo->Synchronous = TRUE;
1450 pGatherIo->CompleteMasterIrp = FALSE;
1452 bCompleteIrp = TRUE;
1454 if( pGatherIo->Synchronous)
1456 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1461 // Setup the MD5 for each extent
1464 AFSSetupMD5Hash( pFcb,
1473 // Pre-emptively set up the count
1476 Irp->IoStatus.Information = ByteCount;
1478 ntStatus = AFSQueueStartIos( pCacheFileObject,
1480 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1485 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1486 AFS_TRACE_LEVEL_VERBOSE,
1487 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1491 if( !NT_SUCCESS( ntStatus))
1494 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1495 AFS_TRACE_LEVEL_VERBOSE,
1496 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1497 &pFcb->NPFcb->Specific.File.ExtentsResource,
1498 PsGetCurrentThread()));
1500 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1504 AFSDereferenceActiveExtents( pStartExtent,
1507 try_return( ntStatus);
1511 // Wait for completion of All IOs we started.
1514 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1520 if( NT_SUCCESS( ntStatus))
1523 ntStatus = pGatherIo->Status;
1526 if( !NT_SUCCESS( ntStatus))
1529 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1530 AFS_TRACE_LEVEL_VERBOSE,
1531 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1532 &pFcb->NPFcb->Specific.File.ExtentsResource,
1533 PsGetCurrentThread()));
1535 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1539 AFSDereferenceActiveExtents( pStartExtent,
1542 try_return( ntStatus);
1547 if( NT_SUCCESS( ntStatus) &&
1548 pStartExtent != NULL &&
1549 Irp->IoStatus.Information > 0)
1555 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1561 // Since this is dirty we can mark the extents dirty now.
1562 // AFSMarkDirty will dereference the extents. Do not call
1563 // AFSDereferenceActiveExtents() in this code path.
1575 // This was an uncached user write - tell the server to do
1576 // the flush when the worker thread next wakes up
1578 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1582 if( pCacheFileObject != NULL)
1584 AFSReleaseCacheFileObject( pCacheFileObject);
1587 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1588 AFS_TRACE_LEVEL_VERBOSE,
1589 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1591 StartingByte.HighPart,
1592 StartingByte.LowPart,
1596 if (NT_SUCCESS(ntStatus) &&
1601 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1607 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1608 AFS_TRACE_LEVEL_VERBOSE,
1609 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1610 &pFcb->NPFcb->Specific.File.ExtentsResource,
1611 PsGetCurrentThread()));
1613 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1618 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1621 if( NULL != pIoRuns &&
1622 stIoRuns != pIoRuns)
1624 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1630 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1631 AFS_TRACE_LEVEL_VERBOSE,
1632 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1635 Irp->IoStatus.Information));
1637 AFSCompleteRequest( Irp, ntStatus);
1646 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1648 IN LARGE_INTEGER StartingByte,
1651 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1652 VOID *pSystemBuffer = NULL;
1653 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1654 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1655 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1656 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1657 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1658 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1659 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1660 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1661 AFSFileIOCB stFileIORequest;
1662 AFSFileIOResultCB stFileIOResult;
1663 ULONG ulResultLen = 0;
1668 Irp->IoStatus.Information = 0;
1670 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1671 AFS_TRACE_LEVEL_VERBOSE,
1672 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1674 StartingByte.HighPart,
1675 StartingByte.LowPart,
1678 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1681 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1682 AFS_TRACE_LEVEL_ERROR,
1683 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1686 pIrpSp->Parameters.Write.Length,
1687 pDevExt->Specific.RDR.MaxIo.QuadPart));
1689 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1693 // Get the mapping for the buffer
1695 pSystemBuffer = AFSLockSystemBuffer( Irp,
1698 if( pSystemBuffer == NULL)
1701 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1702 AFS_TRACE_LEVEL_ERROR,
1703 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1706 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1710 // Issue the request at the service for processing
1713 ulResultLen = sizeof( AFSFileIOResultCB);
1715 RtlZeroMemory( &stFileIORequest,
1716 sizeof( AFSFileIOCB));
1718 RtlZeroMemory( &stFileIOResult,
1719 sizeof( AFSFileIOResultCB));
1721 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1723 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1725 stFileIORequest.IOLength = ByteCount;
1727 stFileIORequest.IOOffset = StartingByte;
1729 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1731 if ( bNoIntermediateBuffering)
1734 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1738 // Update file metadata
1741 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1743 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1745 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1747 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1749 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1752 // Write the data to the service
1755 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1758 &pCcb->DirectoryCB->NameInformation.FileName,
1759 &pFcb->ObjectInformation->FileId,
1760 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1761 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1763 sizeof( AFSFileIOCB),
1767 if( NT_SUCCESS( ntStatus))
1770 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1775 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1776 AFS_TRACE_LEVEL_ERROR,
1777 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1784 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1785 AFS_TRACE_LEVEL_VERBOSE,
1786 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1788 StartingByte.HighPart,
1789 StartingByte.LowPart,
1793 if (NT_SUCCESS(ntStatus) &&
1798 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1801 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1802 AFS_TRACE_LEVEL_VERBOSE,
1803 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1806 Irp->IoStatus.Information));
1808 AFSCompleteRequest( Irp, ntStatus);
1816 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1818 IN LARGE_INTEGER StartingByte,
1820 IN BOOLEAN ForceFlush)
1822 UNREFERENCED_PARAMETER(DeviceObject);
1823 PVOID pSystemBuffer = NULL;
1824 NTSTATUS ntStatus = STATUS_SUCCESS;
1825 IO_STATUS_BLOCK iosbFlush;
1826 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1827 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1828 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1829 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1830 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1831 PMDL pCurrentMdl = Irp->MdlAddress;
1832 LARGE_INTEGER liCurrentOffset;
1837 Irp->IoStatus.Information = 0;
1839 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1845 CcPrepareMdlWrite( pFileObject,
1851 ntStatus = Irp->IoStatus.Status;
1853 __except( EXCEPTION_EXECUTE_HANDLER)
1855 ntStatus = GetExceptionCode();
1857 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1858 AFS_TRACE_LEVEL_ERROR,
1859 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1864 if( !NT_SUCCESS( ntStatus))
1868 // Free up any potentially allocated mdl's
1871 CcMdlWriteComplete( pFileObject,
1875 Irp->MdlAddress = NULL;
1877 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1878 AFS_TRACE_LEVEL_ERROR,
1879 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1884 try_return( ntStatus);
1887 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1889 while( ulTotalLen > 0)
1892 ntStatus = STATUS_SUCCESS;
1894 if( pCurrentMdl != NULL)
1897 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1898 NormalPagePriority);
1900 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1902 if( ulCurrentIO > ulTotalLen)
1904 ulCurrentIO = ulTotalLen;
1910 pSystemBuffer = AFSLockSystemBuffer( Irp,
1913 ulCurrentIO = ulTotalLen;
1916 if( pSystemBuffer == NULL)
1919 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1920 AFS_TRACE_LEVEL_ERROR,
1921 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1924 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1930 if( !CcCopyWrite( pFileObject,
1937 // Failed to process request.
1940 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1941 AFS_TRACE_LEVEL_ERROR,
1942 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1944 &pFileObject->FileName,
1945 liCurrentOffset.QuadPart,
1946 Irp->IoStatus.Status));
1948 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1951 __except( EXCEPTION_EXECUTE_HANDLER)
1954 ntStatus = GetExceptionCode();
1956 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1957 AFS_TRACE_LEVEL_ERROR,
1958 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1960 &pFileObject->FileName,
1961 liCurrentOffset.QuadPart,
1965 if( !NT_SUCCESS( ntStatus))
1967 try_return( ntStatus);
1971 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1977 // We have detected a file we do a write through with.
1980 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1985 if( !NT_SUCCESS( iosbFlush.Status))
1988 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1989 AFS_TRACE_LEVEL_ERROR,
1990 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1992 &pFileObject->FileName,
1993 pFcb->ObjectInformation->FileId.Cell,
1994 pFcb->ObjectInformation->FileId.Volume,
1995 pFcb->ObjectInformation->FileId.Vnode,
1996 pFcb->ObjectInformation->FileId.Unique,
1998 iosbFlush.Information));
2000 try_return( ntStatus = iosbFlush.Status);
2003 __except( EXCEPTION_EXECUTE_HANDLER)
2006 ntStatus = GetExceptionCode();
2008 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2009 AFS_TRACE_LEVEL_ERROR,
2010 "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
2012 &pFileObject->FileName,
2013 liCurrentOffset.QuadPart,
2016 try_return( ntStatus);
2020 if( ulTotalLen <= ulCurrentIO)
2025 liCurrentOffset.QuadPart += ulCurrentIO;
2027 ulTotalLen -= ulCurrentIO;
2029 pCurrentMdl = pCurrentMdl->Next;
2034 if( NT_SUCCESS( ntStatus))
2037 Irp->IoStatus.Information = ByteCount;
2040 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
2043 // Write through asked for... Set things so that we get
2044 // flush when the worker thread next wakes up
2046 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
2050 AFSCompleteRequest( Irp,
2058 // Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
2063 AFSExtendingWrite( IN AFSFcb *Fcb,
2064 IN PFILE_OBJECT FileObject,
2065 IN LONGLONG NewLength)
2067 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
2068 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
2069 NTSTATUS ntStatus = STATUS_SUCCESS;
2070 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
2072 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
2075 Fcb->Header.AllocationSize.QuadPart = NewLength;
2077 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
2080 if( NewLength > Fcb->Header.FileSize.QuadPart)
2083 Fcb->Header.FileSize.QuadPart = NewLength;
2085 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
2092 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
2093 Fcb->ObjectInformation,
2096 if (NT_SUCCESS(ntStatus))
2099 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
2101 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2104 // If the file is currently cached, then let the MM know about the extension
2106 // The CcSetFileSizes call should be made with only the PagingResource held
2107 // which we are currently not holding.
2110 if( CcIsFileCached( FileObject))
2112 CcSetFileSizes( FileObject,
2113 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
2118 Fcb->Header.FileSize = liSaveFileSize;
2119 Fcb->Header.AllocationSize = liSaveAllocation;
2123 // DownConvert file resource to shared
2125 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2131 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2135 UNREFERENCED_PARAMETER(DeviceObject);
2136 NTSTATUS ntStatus = STATUS_SUCCESS;
2137 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2138 AFSFcb *pFcb = NULL;
2139 AFSCcb *pCcb = NULL;
2140 AFSPipeIORequestCB *pIoRequest = NULL;
2141 void *pBuffer = NULL;
2142 AFSPipeIOResultCB stIoResult;
2143 ULONG ulBytesReturned = 0;
2148 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
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 AFSAcquireShared( &pFcb->NPFcb->Resource,
2189 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2190 sizeof( AFSPipeIORequestCB) +
2191 pIrpSp->Parameters.Write.Length,
2192 AFS_GENERIC_MEMORY_14_TAG);
2194 if( pIoRequest == NULL)
2197 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2200 RtlZeroMemory( pIoRequest,
2201 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2203 pIoRequest->RequestId = pCcb->RequestID;
2205 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2207 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2209 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2211 pIrpSp->Parameters.Write.Length);
2213 stIoResult.BytesProcessed = 0;
2215 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2218 // Issue the open request to the service
2221 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2222 AFS_REQUEST_FLAG_SYNCHRONOUS,
2224 &pCcb->DirectoryCB->NameInformation.FileName,
2229 sizeof( AFSPipeIORequestCB) +
2230 pIrpSp->Parameters.Write.Length,
2234 if( !NT_SUCCESS( ntStatus))
2237 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2238 AFS_TRACE_LEVEL_ERROR,
2239 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2243 try_return( ntStatus);
2246 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2247 AFS_TRACE_LEVEL_VERBOSE,
2248 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2249 &pCcb->DirectoryCB->NameInformation.FileName,
2250 stIoResult.BytesProcessed));
2252 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2259 AFSReleaseResource( &pFcb->NPFcb->Resource);
2262 if( pIoRequest != NULL)
2265 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);