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( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
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);
418 if (!CcCanIWrite( pFileObject,
424 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
425 AFS_TRACE_LEVEL_WARNING,
426 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
428 liStartingByte.QuadPart,
430 bRetry ? " RETRY" : ""));
432 ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
434 if ( STATUS_PENDING == ntStatus)
437 bCompleteIrp = FALSE;
442 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
443 AFS_TRACE_LEVEL_ERROR,
444 "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
449 try_return( ntStatus);
454 // Save off the PID if this is not a paging IO
458 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
459 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
460 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
463 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
465 if( ullProcessId == (ULONGLONG)AFSSysProcess)
467 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
468 AFS_TRACE_LEVEL_WARNING,
469 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
478 // - if Paging then we need to do nothing (the precalls will
479 // have acquired the paging resource), for clarity we will collect
480 // the paging resource
481 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
482 // - Otherwise we collect the file shared, check against extending and
493 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
495 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
496 AFS_TRACE_LEVEL_VERBOSE,
497 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
498 &pNPFcb->PagingResource,
499 PsGetCurrentThread()));
501 AFSAcquireShared( &pNPFcb->PagingResource,
504 bReleasePaging = TRUE;
507 // We have the correct lock - we cannot have the wrong one
514 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
515 pFcb->Header.FileSize.QuadPart) ||
516 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
517 liStartingByte.HighPart == -1)) ;
519 if( bExtendingWrite || bNonCachedIo)
522 // Check for lock inversion
526 // For bExtendingWrite the PagingResource is needed to protect
527 // the CcSetFileSizes call in AFSExtendingWrite
530 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
532 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
533 AFS_TRACE_LEVEL_VERBOSE,
534 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
536 PsGetCurrentThread()));
538 AFSAcquireExcl( &pNPFcb->Resource,
543 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
544 AFS_TRACE_LEVEL_VERBOSE,
545 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
546 &pNPFcb->SectionObjectResource,
547 PsGetCurrentThread()));
549 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
552 bReleaseSectionObject = TRUE;
554 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
555 liStartingByte.HighPart == -1)
557 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
559 liStartingByte = pFcb->Header.ValidDataLength;
563 liStartingByte = pFcb->Header.FileSize;
568 // We have the correct lock - even if we don't end up truncating
574 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
576 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
577 AFS_TRACE_LEVEL_VERBOSE,
578 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
580 PsGetCurrentThread()));
582 AFSAcquireShared( &pNPFcb->Resource,
587 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
588 AFS_TRACE_LEVEL_VERBOSE,
589 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
590 &pNPFcb->SectionObjectResource,
591 PsGetCurrentThread()));
593 AFSAcquireShared( &pNPFcb->SectionObjectResource,
596 bReleaseSectionObject = TRUE;
599 // Have things moved? Are we extending? If so, the the lock isn't OK
601 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
606 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
607 AFS_TRACE_LEVEL_VERBOSE,
608 "AFSCommonWrite Releasing Fcb SectionObject lock %p SHARED %08lX\n",
609 &pNPFcb->SectionObjectResource,
610 PsGetCurrentThread()));
612 AFSReleaseResource( &pNPFcb->SectionObjectResource);
614 bReleaseSectionObject = FALSE;
616 AFSReleaseResource( &pNPFcb->Resource);
618 bReleaseMain = FALSE;
629 // Check the BR locks on the file.
632 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
636 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
637 AFS_TRACE_LEVEL_ERROR,
638 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
641 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
647 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
650 // Fcb->NPFcb->Resource is now held SHARED
653 if( !NT_SUCCESS(ntStatus))
656 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
657 AFS_TRACE_LEVEL_ERROR,
658 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
662 try_return( ntStatus );
668 // Fire off the request as appropriate
670 bCompleteIrp = FALSE;
677 // Main resource held Shared
678 // SectionObject resource held exclusive if extending write
681 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
682 AFS_TRACE_LEVEL_VERBOSE,
683 "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
685 liStartingByte.QuadPart,
687 bRetry ? " RETRY" : ""));
689 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
694 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
695 AFS_TRACE_LEVEL_VERBOSE,
696 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
698 liStartingByte.QuadPart,
700 bRetry ? " RETRY" : ""));
702 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
705 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
709 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
715 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
716 AFS_TRACE_LEVEL_VERBOSE,
717 "AFSCommonWrite (%p) Process complete Status %08lX\n",
721 if ( NT_SUCCESS( ntStatus))
729 pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
733 // If this extended the VDL, then update it accordingly.
734 // Increasing the VDL does not require a call to CcSetFileSizes.
737 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
740 pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
743 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
746 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
748 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
753 if ( !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
754 pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
755 bReleaseSectionObject)
758 // Regardless of whether or not the a non-paging non-cached write
759 // succeeds or fails, if the file is cached the contents of the
760 // cache are no longer up to date. A CcPurgeCacheSection must be
761 // performed to force subsequent cached reads to obtain the data
764 // The Fcb Resource is dropped in order to permit filters that perform
765 // an open via a worker thread in response to a purge to do so without
766 // deadlocking. The SectionObjectResource is held across the purge to
767 // prevent racing with other cache operations.
773 AFSReleaseResource( &pNPFcb->Resource);
775 bReleaseMain = FALSE;
781 if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
787 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
788 AFS_TRACE_LEVEL_WARNING,
789 "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
790 pFcb->ObjectInformation->FileId.Cell,
791 pFcb->ObjectInformation->FileId.Volume,
792 pFcb->ObjectInformation->FileId.Vnode,
793 pFcb->ObjectInformation->FileId.Unique));
795 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
798 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
801 DWORD ntStatus2 = GetExceptionCode();
805 "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
806 pFcb->ObjectInformation->FileId.Cell,
807 pFcb->ObjectInformation->FileId.Volume,
808 pFcb->ObjectInformation->FileId.Vnode,
809 pFcb->ObjectInformation->FileId.Unique,
812 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
816 ObDereferenceObject(pFileObject);
818 if( bReleaseSectionObject)
821 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
822 AFS_TRACE_LEVEL_VERBOSE,
823 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
824 &pNPFcb->SectionObjectResource,
825 PsGetCurrentThread()));
827 AFSReleaseResource( &pNPFcb->SectionObjectResource);
833 AFSReleaseResource( &pNPFcb->PagingResource);
839 AFSReleaseResource( &pNPFcb->Resource);
845 AFSCompleteRequest( Irp,
854 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
858 UNREFERENCED_PARAMETER(DeviceObject);
859 NTSTATUS ntStatus = STATUS_SUCCESS;
860 AFSPIOCtlIORequestCB stIORequestCB;
861 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
864 AFSPIOCtlIOResultCB stIOResultCB;
865 ULONG ulBytesReturned = 0;
866 AFSFileID stParentFID;
871 Irp->IoStatus.Information = 0;
873 RtlZeroMemory( &stIORequestCB,
874 sizeof( AFSPIOCtlIORequestCB));
876 if( pIrpSp->Parameters.Write.Length == 0)
880 // Nothing to do in this case
883 try_return( ntStatus);
886 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
888 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
890 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
893 &pFcb->NPFcb->Resource,
894 PsGetCurrentThread()));
896 AFSAcquireShared( &pFcb->NPFcb->Resource,
900 // Get the parent fid to pass to the cm
903 RtlZeroMemory( &stParentFID,
906 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
910 // The parent directory FID of the node
913 stParentFID = pFcb->ObjectInformation->ParentFileId;
917 // Set the control block up
920 stIORequestCB.RequestId = pCcb->RequestID;
922 if( pFcb->ObjectInformation->VolumeCB != NULL)
924 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
928 // Lock down the buffer
931 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
932 pIrpSp->Parameters.Write.Length);
934 if( stIORequestCB.MappedBuffer == NULL)
937 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
940 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
942 stIOResultCB.BytesProcessed = 0;
944 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
947 // Issue the request to the service
950 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
951 AFS_REQUEST_FLAG_SYNCHRONOUS,
957 (void *)&stIORequestCB,
958 sizeof( AFSPIOCtlIORequestCB),
962 if( !NT_SUCCESS( ntStatus))
965 try_return( ntStatus);
969 // Update the length written
972 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
976 if( stIORequestCB.MappedBuffer != NULL)
979 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
986 AFSReleaseResource( &pFcb->NPFcb->Resource);
994 // This function is called when we know we have to read from the AFS Cache.
996 // It ensures that we have exents for the entirety of the write and
997 // then pins the extents into memory (meaning that although we may
998 // add we will not remove). Then it creates a scatter gather write
999 // and fires off the IRPs
1003 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1005 IN LARGE_INTEGER StartingByte,
1008 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1009 VOID *pSystemBuffer = NULL;
1010 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1011 BOOLEAN bLocked = FALSE;
1012 BOOLEAN bCompleteIrp = TRUE;
1013 AFSGatherIo *pGatherIo = NULL;
1014 AFSIoRun *pIoRuns = NULL;
1015 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
1016 ULONG extentsCount = 0, runCount = 0;
1017 AFSExtent *pStartExtent = NULL;
1018 AFSExtent *pIgnoreExtent = NULL;
1019 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1020 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1021 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1022 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1023 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1024 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1025 LARGE_INTEGER liCurrentTime, liLastRequestTime;
1026 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1027 PFILE_OBJECT pCacheFileObject = NULL;
1028 BOOLEAN bDerefExtents = FALSE;
1033 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1034 AFS_TRACE_LEVEL_VERBOSE,
1035 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1037 StartingByte.HighPart,
1038 StartingByte.LowPart,
1041 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1044 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1045 AFS_TRACE_LEVEL_ERROR,
1046 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1049 pIrpSp->Parameters.Write.Length,
1050 pDevExt->Specific.RDR.MaxIo.QuadPart));
1052 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1056 // Get the mapping for the buffer
1058 pSystemBuffer = AFSLockSystemBuffer( Irp,
1061 if( pSystemBuffer == NULL)
1064 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1065 AFS_TRACE_LEVEL_ERROR,
1066 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
1069 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1074 // Provoke a get of the extents - if we need to.
1077 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1078 AFS_TRACE_LEVEL_VERBOSE,
1079 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1080 pFcb->ObjectInformation->FileId.Cell,
1081 pFcb->ObjectInformation->FileId.Volume,
1082 pFcb->ObjectInformation->FileId.Vnode,
1083 pFcb->ObjectInformation->FileId.Unique,
1084 StartingByte.QuadPart,
1087 ntStatus = AFSRequestExtentsAsync( pFcb,
1092 if (!NT_SUCCESS(ntStatus))
1095 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1096 AFS_TRACE_LEVEL_ERROR,
1097 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1101 try_return( ntStatus);
1104 KeQueryTickCount( &liLastRequestTime);
1109 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1110 AFS_TRACE_LEVEL_VERBOSE,
1111 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1112 &pFcb->NPFcb->Specific.File.ExtentsResource,
1113 PsGetCurrentThread()));
1115 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1117 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1120 pStartExtent = NULL;
1121 pIgnoreExtent = NULL;
1123 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1128 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1130 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1131 AFS_TRACE_LEVEL_VERBOSE,
1132 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1133 &pFcb->NPFcb->Specific.File.ExtentsResource,
1134 PsGetCurrentThread()));
1136 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1140 // We will re-request the extents after waiting for them
1143 KeQueryTickCount( &liCurrentTime);
1145 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1148 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1149 AFS_TRACE_LEVEL_VERBOSE,
1150 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1151 pFcb->ObjectInformation->FileId.Cell,
1152 pFcb->ObjectInformation->FileId.Volume,
1153 pFcb->ObjectInformation->FileId.Vnode,
1154 pFcb->ObjectInformation->FileId.Unique,
1155 StartingByte.QuadPart,
1158 ntStatus = AFSRequestExtentsAsync( pFcb,
1163 if (!NT_SUCCESS(ntStatus))
1166 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1167 AFS_TRACE_LEVEL_ERROR,
1168 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1172 try_return( ntStatus);
1175 KeQueryTickCount( &liLastRequestTime);
1179 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1180 AFS_TRACE_LEVEL_VERBOSE,
1181 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1182 pFcb->ObjectInformation->FileId.Cell,
1183 pFcb->ObjectInformation->FileId.Volume,
1184 pFcb->ObjectInformation->FileId.Vnode,
1185 pFcb->ObjectInformation->FileId.Unique,
1186 StartingByte.QuadPart,
1193 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1195 if (!NT_SUCCESS(ntStatus))
1198 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1199 AFS_TRACE_LEVEL_ERROR,
1200 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1201 pFcb->ObjectInformation->FileId.Cell,
1202 pFcb->ObjectInformation->FileId.Volume,
1203 pFcb->ObjectInformation->FileId.Vnode,
1204 pFcb->ObjectInformation->FileId.Unique,
1205 StartingByte.QuadPart,
1209 try_return( ntStatus);
1214 // As per the read path -
1217 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1218 AFS_TRACE_LEVEL_VERBOSE,
1219 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1220 pFcb->ObjectInformation->FileId.Cell,
1221 pFcb->ObjectInformation->FileId.Volume,
1222 pFcb->ObjectInformation->FileId.Vnode,
1223 pFcb->ObjectInformation->FileId.Unique,
1224 StartingByte.QuadPart,
1227 ntStatus = AFSGetExtents( pFcb,
1234 if (!NT_SUCCESS(ntStatus))
1237 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1238 AFS_TRACE_LEVEL_ERROR,
1239 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1243 try_return( ntStatus );
1246 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1247 AFS_TRACE_LEVEL_VERBOSE,
1248 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1253 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1256 Irp->IoStatus.Information = ByteCount;
1260 // Setup the MD5 for each extent
1263 AFSSetupMD5Hash( pFcb,
1271 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1277 if (!NT_SUCCESS(ntStatus))
1280 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1281 AFS_TRACE_LEVEL_ERROR,
1282 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1287 try_return( ntStatus);
1291 // Retrieve the cache file object
1294 pCacheFileObject = AFSReferenceCacheFileObject();
1296 if( pCacheFileObject == NULL)
1299 ntStatus = STATUS_DEVICE_NOT_READY;
1301 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1302 AFS_TRACE_LEVEL_ERROR,
1303 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1304 pFcb->ObjectInformation->FileId.Cell,
1305 pFcb->ObjectInformation->FileId.Volume,
1306 pFcb->ObjectInformation->FileId.Vnode,
1307 pFcb->ObjectInformation->FileId.Unique,
1308 StartingByte.QuadPart,
1312 try_return( ntStatus);
1315 if (runCount > AFS_MAX_STACK_IO_RUNS)
1318 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1319 runCount * sizeof( AFSIoRun ),
1321 if (NULL == pIoRuns)
1324 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1325 AFS_TRACE_LEVEL_ERROR,
1326 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1329 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1338 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1340 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1349 if (!NT_SUCCESS(ntStatus))
1352 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1353 AFS_TRACE_LEVEL_ERROR,
1354 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1358 try_return( ntStatus );
1361 AFSReferenceActiveExtents( pStartExtent,
1364 bDerefExtents = TRUE;
1366 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1367 AFS_TRACE_LEVEL_VERBOSE,
1368 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1369 &pFcb->NPFcb->Specific.File.ExtentsResource,
1370 PsGetCurrentThread()));
1372 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1375 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1376 sizeof( AFSGatherIo),
1379 if (NULL == pGatherIo)
1382 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1383 AFS_TRACE_LEVEL_ERROR,
1384 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1387 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1388 AFS_TRACE_LEVEL_VERBOSE,
1389 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1390 &pFcb->NPFcb->Specific.File.ExtentsResource,
1391 PsGetCurrentThread()));
1393 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1397 AFSDereferenceActiveExtents( pStartExtent,
1400 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1403 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1406 // Initialize count to 1, that was we won't get an early
1407 // completion if the first irp completes before the second is
1410 pGatherIo->Count = 1;
1411 pGatherIo->Status = STATUS_SUCCESS;
1412 pGatherIo->MasterIrp = Irp;
1413 pGatherIo->Synchronous = TRUE;
1414 pGatherIo->CompleteMasterIrp = FALSE;
1416 bCompleteIrp = TRUE;
1418 if( pGatherIo->Synchronous)
1420 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1425 // Setup the MD5 for each extent
1428 AFSSetupMD5Hash( pFcb,
1437 // Pre-emptively set up the count
1440 Irp->IoStatus.Information = ByteCount;
1442 ntStatus = AFSQueueStartIos( pCacheFileObject,
1444 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1449 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1450 AFS_TRACE_LEVEL_VERBOSE,
1451 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1455 if( !NT_SUCCESS( ntStatus))
1458 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1459 AFS_TRACE_LEVEL_VERBOSE,
1460 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1461 &pFcb->NPFcb->Specific.File.ExtentsResource,
1462 PsGetCurrentThread()));
1464 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1468 AFSDereferenceActiveExtents( pStartExtent,
1471 try_return( ntStatus);
1475 // Wait for completion of All IOs we started.
1478 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1484 if( NT_SUCCESS( ntStatus))
1487 ntStatus = pGatherIo->Status;
1490 if( !NT_SUCCESS( ntStatus))
1493 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1494 AFS_TRACE_LEVEL_VERBOSE,
1495 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1496 &pFcb->NPFcb->Specific.File.ExtentsResource,
1497 PsGetCurrentThread()));
1499 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1503 AFSDereferenceActiveExtents( pStartExtent,
1506 try_return( ntStatus);
1511 if( NT_SUCCESS( ntStatus) &&
1512 pStartExtent != NULL &&
1513 Irp->IoStatus.Information > 0)
1519 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1525 // Since this is dirty we can mark the extents dirty now.
1526 // AFSMarkDirty will dereference the extents. Do not call
1527 // AFSDereferenceActiveExtents() in this code path.
1539 // This was an uncached user write - tell the server to do
1540 // the flush when the worker thread next wakes up
1542 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1546 if( pCacheFileObject != NULL)
1548 AFSReleaseCacheFileObject( pCacheFileObject);
1551 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1552 AFS_TRACE_LEVEL_VERBOSE,
1553 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1555 StartingByte.HighPart,
1556 StartingByte.LowPart,
1560 if (NT_SUCCESS(ntStatus) &&
1565 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1571 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1572 AFS_TRACE_LEVEL_VERBOSE,
1573 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1574 &pFcb->NPFcb->Specific.File.ExtentsResource,
1575 PsGetCurrentThread()));
1577 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1582 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1585 if( NULL != pIoRuns &&
1586 stIoRuns != pIoRuns)
1588 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1594 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1595 AFS_TRACE_LEVEL_VERBOSE,
1596 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1599 Irp->IoStatus.Information));
1601 AFSCompleteRequest( Irp, ntStatus);
1610 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1612 IN LARGE_INTEGER StartingByte,
1615 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1616 VOID *pSystemBuffer = NULL;
1617 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1618 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1619 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1620 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1621 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1622 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1623 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1624 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1625 AFSFileIOCB stFileIORequest;
1626 AFSFileIOResultCB stFileIOResult;
1627 ULONG ulResultLen = 0;
1632 Irp->IoStatus.Information = 0;
1634 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1635 AFS_TRACE_LEVEL_VERBOSE,
1636 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1638 StartingByte.HighPart,
1639 StartingByte.LowPart,
1642 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1645 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1646 AFS_TRACE_LEVEL_ERROR,
1647 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1650 pIrpSp->Parameters.Write.Length,
1651 pDevExt->Specific.RDR.MaxIo.QuadPart));
1653 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1657 // Get the mapping for the buffer
1659 pSystemBuffer = AFSLockSystemBuffer( Irp,
1662 if( pSystemBuffer == NULL)
1665 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1666 AFS_TRACE_LEVEL_ERROR,
1667 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1670 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1674 // Issue the request at the service for processing
1677 ulResultLen = sizeof( AFSFileIOResultCB);
1679 RtlZeroMemory( &stFileIORequest,
1680 sizeof( AFSFileIOCB));
1682 RtlZeroMemory( &stFileIOResult,
1683 sizeof( AFSFileIOResultCB));
1685 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1687 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1689 stFileIORequest.IOLength = ByteCount;
1691 stFileIORequest.IOOffset = StartingByte;
1693 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1695 if ( bNoIntermediateBuffering)
1698 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1702 // Update file metadata
1705 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1707 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1709 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1711 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1713 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1716 // Write the data to the service
1719 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1722 &pCcb->DirectoryCB->NameInformation.FileName,
1723 &pFcb->ObjectInformation->FileId,
1724 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1725 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1727 sizeof( AFSFileIOCB),
1731 if( NT_SUCCESS( ntStatus))
1734 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1739 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1740 AFS_TRACE_LEVEL_ERROR,
1741 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1748 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1749 AFS_TRACE_LEVEL_VERBOSE,
1750 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1752 StartingByte.HighPart,
1753 StartingByte.LowPart,
1757 if (NT_SUCCESS(ntStatus) &&
1762 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1765 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1766 AFS_TRACE_LEVEL_VERBOSE,
1767 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1770 Irp->IoStatus.Information));
1772 AFSCompleteRequest( Irp, ntStatus);
1780 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1782 IN LARGE_INTEGER StartingByte,
1784 IN BOOLEAN ForceFlush)
1786 UNREFERENCED_PARAMETER(DeviceObject);
1787 PVOID pSystemBuffer = NULL;
1788 NTSTATUS ntStatus = STATUS_SUCCESS;
1789 IO_STATUS_BLOCK iosbFlush;
1790 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1791 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1792 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1793 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1794 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1795 PMDL pCurrentMdl = Irp->MdlAddress;
1796 LARGE_INTEGER liCurrentOffset;
1801 Irp->IoStatus.Information = 0;
1803 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1809 CcPrepareMdlWrite( pFileObject,
1815 ntStatus = Irp->IoStatus.Status;
1817 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1819 ntStatus = GetExceptionCode();
1821 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1822 AFS_TRACE_LEVEL_ERROR,
1823 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1828 if( !NT_SUCCESS( ntStatus))
1832 // Free up any potentially allocated mdl's
1835 CcMdlWriteComplete( pFileObject,
1839 Irp->MdlAddress = NULL;
1841 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1842 AFS_TRACE_LEVEL_ERROR,
1843 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1848 try_return( ntStatus);
1851 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1853 while( ulTotalLen > 0)
1856 ntStatus = STATUS_SUCCESS;
1858 if( pCurrentMdl != NULL)
1861 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1862 NormalPagePriority);
1864 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1866 if( ulCurrentIO > ulTotalLen)
1868 ulCurrentIO = ulTotalLen;
1874 pSystemBuffer = AFSLockSystemBuffer( Irp,
1877 ulCurrentIO = ulTotalLen;
1880 if( pSystemBuffer == NULL)
1883 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1884 AFS_TRACE_LEVEL_ERROR,
1885 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1888 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1894 if( !CcCopyWrite( pFileObject,
1901 // Failed to process request.
1904 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1905 AFS_TRACE_LEVEL_ERROR,
1906 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1908 &pFileObject->FileName,
1909 liCurrentOffset.QuadPart,
1910 Irp->IoStatus.Status));
1912 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1915 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1918 ntStatus = GetExceptionCode();
1920 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1921 AFS_TRACE_LEVEL_ERROR,
1922 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1924 &pFileObject->FileName,
1925 liCurrentOffset.QuadPart,
1929 if( !NT_SUCCESS( ntStatus))
1931 try_return( ntStatus);
1935 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1941 // We have detected a file we do a write through with.
1944 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1949 if( !NT_SUCCESS( iosbFlush.Status))
1952 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1953 AFS_TRACE_LEVEL_ERROR,
1954 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1956 &pFileObject->FileName,
1957 pFcb->ObjectInformation->FileId.Cell,
1958 pFcb->ObjectInformation->FileId.Volume,
1959 pFcb->ObjectInformation->FileId.Vnode,
1960 pFcb->ObjectInformation->FileId.Unique,
1962 iosbFlush.Information));
1964 try_return( ntStatus = iosbFlush.Status);
1967 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1970 ntStatus = GetExceptionCode();
1972 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1973 AFS_TRACE_LEVEL_ERROR,
1974 "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
1976 &pFileObject->FileName,
1977 liCurrentOffset.QuadPart,
1980 try_return( ntStatus);
1984 if( ulTotalLen <= ulCurrentIO)
1989 liCurrentOffset.QuadPart += ulCurrentIO;
1991 ulTotalLen -= ulCurrentIO;
1993 pCurrentMdl = pCurrentMdl->Next;
1998 if( NT_SUCCESS( ntStatus))
2001 Irp->IoStatus.Information = ByteCount;
2004 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
2007 // Write through asked for... Set things so that we get
2008 // flush when the worker thread next wakes up
2010 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
2014 AFSCompleteRequest( Irp,
2022 // Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
2027 AFSExtendingWrite( IN AFSFcb *Fcb,
2028 IN PFILE_OBJECT FileObject,
2029 IN LONGLONG NewLength)
2031 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
2032 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
2033 NTSTATUS ntStatus = STATUS_SUCCESS;
2034 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
2036 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
2039 Fcb->Header.AllocationSize.QuadPart = NewLength;
2041 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
2044 if( NewLength > Fcb->Header.FileSize.QuadPart)
2047 Fcb->Header.FileSize.QuadPart = NewLength;
2049 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
2056 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
2057 Fcb->ObjectInformation,
2060 if (NT_SUCCESS(ntStatus))
2063 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
2065 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2068 // If the file is currently cached, then let the MM know about the extension
2070 // The CcSetFileSizes call should be made with only the PagingResource held
2071 // which we are currently not holding.
2074 if( CcIsFileCached( FileObject))
2076 CcSetFileSizes( FileObject,
2077 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
2082 Fcb->Header.FileSize = liSaveFileSize;
2083 Fcb->Header.AllocationSize = liSaveAllocation;
2087 // DownConvert file resource to shared
2089 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2095 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2099 UNREFERENCED_PARAMETER(DeviceObject);
2100 NTSTATUS ntStatus = STATUS_SUCCESS;
2101 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2102 AFSFcb *pFcb = NULL;
2103 AFSCcb *pCcb = NULL;
2104 AFSPipeIORequestCB *pIoRequest = NULL;
2105 void *pBuffer = NULL;
2106 AFSPipeIOResultCB stIoResult;
2107 ULONG ulBytesReturned = 0;
2112 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2114 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2116 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2117 AFS_TRACE_LEVEL_VERBOSE,
2118 "AFSShareWrite On pipe %wZ Length %08lX\n",
2119 &pCcb->DirectoryCB->NameInformation.FileName,
2120 pIrpSp->Parameters.Write.Length));
2122 if( pIrpSp->Parameters.Write.Length == 0)
2126 // Nothing to do in this case
2129 try_return( ntStatus);
2133 // Retrieve the buffer for the read request
2136 pBuffer = AFSLockSystemBuffer( Irp,
2137 pIrpSp->Parameters.Write.Length);
2139 if( pBuffer == NULL)
2142 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2143 AFS_TRACE_LEVEL_ERROR,
2144 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2145 &pCcb->DirectoryCB->NameInformation.FileName));
2147 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2150 AFSAcquireShared( &pFcb->NPFcb->Resource,
2153 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2154 sizeof( AFSPipeIORequestCB) +
2155 pIrpSp->Parameters.Write.Length,
2156 AFS_GENERIC_MEMORY_14_TAG);
2158 if( pIoRequest == NULL)
2161 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2164 RtlZeroMemory( pIoRequest,
2165 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2167 pIoRequest->RequestId = pCcb->RequestID;
2169 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2171 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2173 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2175 pIrpSp->Parameters.Write.Length);
2177 stIoResult.BytesProcessed = 0;
2179 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2182 // Issue the open request to the service
2185 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2186 AFS_REQUEST_FLAG_SYNCHRONOUS,
2188 &pCcb->DirectoryCB->NameInformation.FileName,
2193 sizeof( AFSPipeIORequestCB) +
2194 pIrpSp->Parameters.Write.Length,
2198 if( !NT_SUCCESS( ntStatus))
2201 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2202 AFS_TRACE_LEVEL_ERROR,
2203 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2207 try_return( ntStatus);
2210 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2211 AFS_TRACE_LEVEL_VERBOSE,
2212 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2213 &pCcb->DirectoryCB->NameInformation.FileName,
2214 stIoResult.BytesProcessed));
2216 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2223 AFSReleaseResource( &pFcb->NPFcb->Resource);
2226 if( pIoRequest != NULL)
2229 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);