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 bCompleteIrp = TRUE;
124 BOOLEAN bForceFlush = FALSE;
126 HANDLE hCallingUser = OnBehalfOf;
127 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
128 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
130 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
135 Irp->IoStatus.Information = 0;
137 pFileObject = pIrpSp->FileObject;
140 // Extract the fileobject references
143 pFcb = (AFSFcb *)pFileObject->FsContext;
144 pCcb = (AFSCcb *)pFileObject->FsContext2;
146 ObReferenceObject( pFileObject);
151 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
152 AFS_TRACE_LEVEL_ERROR,
153 "AFSCommonWrite Attempted write (%p) when pFcb == NULL\n",
156 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
159 pNPFcb = pFcb->NPFcb;
162 // If we are in shutdown mode then fail the request
165 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
168 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
169 AFS_TRACE_LEVEL_WARNING,
170 "AFSCommonWrite (%p) Open request after shutdown\n",
173 try_return( ntStatus = STATUS_TOO_LATE);
176 liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
177 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
178 bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
179 ulByteCount = pIrpSp->Parameters.Write.Length;
181 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
182 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
183 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
186 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
187 AFS_TRACE_LEVEL_ERROR,
188 "AFSCommonWrite Attempted write (%p) on an invalid node type %08lX\n",
190 pFcb->Header.NodeTypeCode));
192 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
196 // If this is a write against an IOCtl node then handle it
197 // in a different pathway
200 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
203 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
204 AFS_TRACE_LEVEL_VERBOSE,
205 "AFSCommonWrite (%p) Processing file (PIOCTL) Offset %0I64X Length %08lX Irp Flags %08lX\n",
207 liStartingByte.QuadPart,
211 ntStatus = AFSIOCtlWrite( DeviceObject,
214 try_return( ntStatus);
216 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
219 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
220 AFS_TRACE_LEVEL_VERBOSE,
221 "AFSCommonWrite (%p) Processing file (SHARE) Offset %0I64X Length %08lX Irp Flags %08lX\n",
223 liStartingByte.QuadPart,
227 ntStatus = AFSShareWrite( DeviceObject,
230 try_return( ntStatus);
234 // Is the Cache not there yet? Exit.
236 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
237 !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
238 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
241 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
242 AFS_TRACE_LEVEL_ERROR,
243 "AFSCommonWrite (%p) Request failed due to AFS cache closed\n",
246 try_return( ntStatus = STATUS_TOO_LATE );
249 if( pFcb->ObjectInformation->VolumeCB != NULL &&
250 BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
253 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
254 AFS_TRACE_LEVEL_ERROR,
255 "AFSCommonWrite (%p) Request failed due to read only volume\n",
258 try_return( ntStatus = STATUS_ACCESS_DENIED);
262 // We need to know on whose behalf we have been called (which
263 // we will eventually tell to the server - for non paging
264 // writes). If we were posted then we were told. If this is
265 // the first time we saw the irp then we grab it now.
267 if( NULL == OnBehalfOf )
270 hCallingUser = PsGetCurrentProcessId();
275 hCallingUser = OnBehalfOf;
279 // Check for zero length write
282 if( ulByteCount == 0)
285 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
286 AFS_TRACE_LEVEL_VERBOSE,
287 "AFSCommonWrite (%p) Request completed due to zero length\n",
290 try_return( ntStatus);
294 // Is this Fcb valid???
297 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
300 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
301 AFS_TRACE_LEVEL_ERROR,
302 "AFSCommonWrite (%p) Failing request due to INVALID fcb\n",
305 try_return( ntStatus = STATUS_FILE_DELETED);
308 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
309 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
312 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
313 AFS_TRACE_LEVEL_ERROR,
314 "AFSCommonWrite (%p) Request failed due to file deleted\n",
317 try_return( ntStatus = STATUS_FILE_DELETED);
320 if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
323 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
324 AFS_TRACE_LEVEL_VERBOSE,
325 "AFSCommonWrite (%p) IRP_MN_COMPLETE being processed\n",
328 CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
331 // Mdl is now Deallocated
334 Irp->MdlAddress = NULL;
336 try_return( ntStatus = STATUS_SUCCESS );
340 // If we get a non cached IO for a cached file we should do a purge.
341 // For now we will just promote to cached
343 if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
345 bNonCachedIo = FALSE;
349 if ( !bNonCachedIo && !bPagingIo)
352 if( pFileObject->PrivateCacheMap == NULL)
355 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
356 AFS_TRACE_LEVEL_VERBOSE,
357 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
358 &pNPFcb->SectionObjectResource,
359 PsGetCurrentThread()));
361 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
364 bReleaseSectionObject = TRUE;
369 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
370 AFS_TRACE_LEVEL_VERBOSE,
371 "AFSCommonWrite Initialize caching on Fcb %p FileObject %p\n",
375 CcInitializeCacheMap( pFileObject,
376 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
378 AFSLibCacheManagerCallbacks,
381 CcSetReadAheadGranularity( pFileObject,
382 pDeviceExt->Specific.RDR.MaximumRPCLength);
384 CcSetDirtyPageThreshold( pFileObject,
385 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
387 __except( EXCEPTION_EXECUTE_HANDLER)
390 ntStatus = GetExceptionCode();
392 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
393 AFS_TRACE_LEVEL_ERROR,
394 "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
399 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
400 AFS_TRACE_LEVEL_VERBOSE,
401 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
402 &pNPFcb->SectionObjectResource,
403 PsGetCurrentThread()));
405 AFSReleaseResource( &pNPFcb->SectionObjectResource);
407 bReleaseSectionObject = FALSE;
409 if( !NT_SUCCESS( ntStatus))
412 try_return( ntStatus);
416 if (!CcCanIWrite( pFileObject,
422 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
423 AFS_TRACE_LEVEL_WARNING,
424 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
426 liStartingByte.QuadPart,
428 bRetry ? " RETRY" : ""));
430 ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
432 if ( STATUS_PENDING == ntStatus)
435 bCompleteIrp = FALSE;
440 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
441 AFS_TRACE_LEVEL_ERROR,
442 "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
447 try_return( ntStatus);
452 // Save off the PID if this is not a paging IO
456 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
457 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
458 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
461 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
463 if( ullProcessId == (ULONGLONG)AFSSysProcess)
465 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
466 AFS_TRACE_LEVEL_WARNING,
467 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
476 // - if Paging then we need to do nothing (the precalls will
477 // have acquired the paging resource), for clarity we will collect
478 // the paging resource
479 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
480 // - Otherwise we collect the file shared, check against extending and
491 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
493 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
494 AFS_TRACE_LEVEL_VERBOSE,
495 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
496 &pNPFcb->PagingResource,
497 PsGetCurrentThread()));
499 AFSAcquireShared( &pNPFcb->PagingResource,
502 bReleasePaging = TRUE;
505 // We have the correct lock - we cannot have the wrong one
512 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
513 pFcb->Header.FileSize.QuadPart) ||
514 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
515 liStartingByte.HighPart == -1)) ;
520 // Check for lock inversion
523 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
525 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
526 AFS_TRACE_LEVEL_VERBOSE,
527 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
529 PsGetCurrentThread()));
531 AFSAcquireExcl( &pNPFcb->Resource,
536 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
537 AFS_TRACE_LEVEL_VERBOSE,
538 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
539 &pNPFcb->SectionObjectResource,
540 PsGetCurrentThread()));
542 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
545 bReleaseSectionObject = TRUE;
547 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
548 liStartingByte.HighPart == -1)
550 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
552 liStartingByte = pFcb->Header.ValidDataLength;
556 liStartingByte = pFcb->Header.FileSize;
561 // We have the correct lock - even if we don't end up truncating
567 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
569 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
570 AFS_TRACE_LEVEL_VERBOSE,
571 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
573 PsGetCurrentThread()));
575 AFSAcquireShared( &pNPFcb->Resource,
580 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
581 AFS_TRACE_LEVEL_VERBOSE,
582 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
583 &pNPFcb->SectionObjectResource,
584 PsGetCurrentThread()));
586 AFSAcquireShared( &pNPFcb->SectionObjectResource,
589 bReleaseSectionObject = TRUE;
592 // Have things moved? Are we extending? If so, the the lock isn't OK
594 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
598 AFSReleaseResource( &pNPFcb->Resource);
600 bReleaseMain = FALSE;
611 // Check the BR locks on the file.
614 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
618 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
619 AFS_TRACE_LEVEL_ERROR,
620 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
623 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
629 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
631 if( !NT_SUCCESS(ntStatus))
634 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
635 AFS_TRACE_LEVEL_ERROR,
636 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
640 try_return( ntStatus );
646 // Fire off the request as appropriate
648 bCompleteIrp = FALSE;
655 // Main and SectionObject resources held Shared
658 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
659 AFS_TRACE_LEVEL_VERBOSE,
660 "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
662 liStartingByte.QuadPart,
664 bRetry ? " RETRY" : ""));
666 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
673 // if bPagingIo, Paging Resource held Shared
674 // else Main and SectionObject resources held Shared
677 if( bReleaseSectionObject)
680 AFSReleaseResource( &pNPFcb->SectionObjectResource);
682 bReleaseSectionObject = FALSE;
688 AFSReleaseResource( &pNPFcb->PagingResource);
690 bReleasePaging = FALSE;
696 AFSReleaseResource( &pNPFcb->Resource);
698 bReleaseMain = FALSE;
701 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
702 AFS_TRACE_LEVEL_VERBOSE,
703 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
705 liStartingByte.QuadPart,
707 bRetry ? " RETRY" : ""));
709 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
712 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
716 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
722 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
723 AFS_TRACE_LEVEL_VERBOSE,
724 "AFSCommonWrite (%p) Process complete Status %08lX\n",
728 ObDereferenceObject(pFileObject);
730 if( bReleaseSectionObject)
733 AFSReleaseResource( &pNPFcb->SectionObjectResource);
739 AFSReleaseResource( &pNPFcb->PagingResource);
745 AFSReleaseResource( &pNPFcb->Resource);
751 AFSCompleteRequest( Irp,
760 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
764 UNREFERENCED_PARAMETER(DeviceObject);
765 NTSTATUS ntStatus = STATUS_SUCCESS;
766 AFSPIOCtlIORequestCB stIORequestCB;
767 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
770 AFSPIOCtlIOResultCB stIOResultCB;
771 ULONG ulBytesReturned = 0;
772 AFSFileID stParentFID;
777 Irp->IoStatus.Information = 0;
779 RtlZeroMemory( &stIORequestCB,
780 sizeof( AFSPIOCtlIORequestCB));
782 if( pIrpSp->Parameters.Write.Length == 0)
786 // Nothing to do in this case
789 try_return( ntStatus);
792 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
794 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
796 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
797 AFS_TRACE_LEVEL_VERBOSE,
798 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
799 &pFcb->NPFcb->Resource,
800 PsGetCurrentThread()));
802 AFSAcquireShared( &pFcb->NPFcb->Resource,
806 // Get the parent fid to pass to the cm
809 RtlZeroMemory( &stParentFID,
812 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
816 // The parent directory FID of the node
819 stParentFID = pFcb->ObjectInformation->ParentFileId;
823 // Set the control block up
826 stIORequestCB.RequestId = pCcb->RequestID;
828 if( pFcb->ObjectInformation->VolumeCB != NULL)
830 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
834 // Lock down the buffer
837 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
838 pIrpSp->Parameters.Write.Length);
840 if( stIORequestCB.MappedBuffer == NULL)
843 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
846 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
848 stIOResultCB.BytesProcessed = 0;
850 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
853 // Issue the request to the service
856 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
857 AFS_REQUEST_FLAG_SYNCHRONOUS,
863 (void *)&stIORequestCB,
864 sizeof( AFSPIOCtlIORequestCB),
868 if( !NT_SUCCESS( ntStatus))
871 try_return( ntStatus);
875 // Update the length written
878 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
882 if( stIORequestCB.MappedBuffer != NULL)
885 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
892 AFSReleaseResource( &pFcb->NPFcb->Resource);
900 // This function is called when we know we have to read from the AFS Cache.
902 // It ensures that we have exents for the entirety of the write and
903 // then pins the extents into memory (meaning that although we may
904 // add we will not remove). Then it creates a scatter gather write
905 // and fires off the IRPs
909 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
911 IN LARGE_INTEGER StartingByte,
914 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
915 VOID *pSystemBuffer = NULL;
916 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
917 BOOLEAN bLocked = FALSE;
918 BOOLEAN bCompleteIrp = TRUE;
919 AFSGatherIo *pGatherIo = NULL;
920 AFSIoRun *pIoRuns = NULL;
921 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
922 ULONG extentsCount = 0, runCount = 0;
923 AFSExtent *pStartExtent = NULL;
924 AFSExtent *pIgnoreExtent = NULL;
925 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
926 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
927 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
928 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
929 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
930 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
931 LARGE_INTEGER liCurrentTime, liLastRequestTime;
932 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
933 PFILE_OBJECT pCacheFileObject = NULL;
934 BOOLEAN bDerefExtents = FALSE;
939 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
940 AFS_TRACE_LEVEL_VERBOSE,
941 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
943 StartingByte.HighPart,
944 StartingByte.LowPart,
947 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
950 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
951 AFS_TRACE_LEVEL_ERROR,
952 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
955 pIrpSp->Parameters.Write.Length,
956 pDevExt->Specific.RDR.MaxIo.QuadPart));
958 try_return( ntStatus = STATUS_UNSUCCESSFUL);
962 // Get the mapping for the buffer
964 pSystemBuffer = AFSLockSystemBuffer( Irp,
967 if( pSystemBuffer == NULL)
970 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
971 AFS_TRACE_LEVEL_ERROR,
972 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
975 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
980 // Provoke a get of the extents - if we need to.
983 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
984 AFS_TRACE_LEVEL_VERBOSE,
985 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
986 pFcb->ObjectInformation->FileId.Cell,
987 pFcb->ObjectInformation->FileId.Volume,
988 pFcb->ObjectInformation->FileId.Vnode,
989 pFcb->ObjectInformation->FileId.Unique,
990 StartingByte.QuadPart,
993 ntStatus = AFSRequestExtentsAsync( pFcb,
998 if (!NT_SUCCESS(ntStatus))
1001 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1002 AFS_TRACE_LEVEL_ERROR,
1003 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1007 try_return( ntStatus);
1010 KeQueryTickCount( &liLastRequestTime);
1015 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1016 AFS_TRACE_LEVEL_VERBOSE,
1017 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1018 &pFcb->NPFcb->Specific.File.ExtentsResource,
1019 PsGetCurrentThread()));
1021 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1023 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1026 pStartExtent = NULL;
1027 pIgnoreExtent = NULL;
1029 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1034 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1036 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1037 AFS_TRACE_LEVEL_VERBOSE,
1038 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1039 &pFcb->NPFcb->Specific.File.ExtentsResource,
1040 PsGetCurrentThread()));
1042 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1046 // We will re-request the extents after waiting for them
1049 KeQueryTickCount( &liCurrentTime);
1051 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1054 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1055 AFS_TRACE_LEVEL_VERBOSE,
1056 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1057 pFcb->ObjectInformation->FileId.Cell,
1058 pFcb->ObjectInformation->FileId.Volume,
1059 pFcb->ObjectInformation->FileId.Vnode,
1060 pFcb->ObjectInformation->FileId.Unique,
1061 StartingByte.QuadPart,
1064 ntStatus = AFSRequestExtentsAsync( pFcb,
1069 if (!NT_SUCCESS(ntStatus))
1072 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1073 AFS_TRACE_LEVEL_ERROR,
1074 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1078 try_return( ntStatus);
1081 KeQueryTickCount( &liLastRequestTime);
1085 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1086 AFS_TRACE_LEVEL_VERBOSE,
1087 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1088 pFcb->ObjectInformation->FileId.Cell,
1089 pFcb->ObjectInformation->FileId.Volume,
1090 pFcb->ObjectInformation->FileId.Vnode,
1091 pFcb->ObjectInformation->FileId.Unique,
1092 StartingByte.QuadPart,
1099 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1101 if (!NT_SUCCESS(ntStatus))
1104 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1105 AFS_TRACE_LEVEL_ERROR,
1106 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1107 pFcb->ObjectInformation->FileId.Cell,
1108 pFcb->ObjectInformation->FileId.Volume,
1109 pFcb->ObjectInformation->FileId.Vnode,
1110 pFcb->ObjectInformation->FileId.Unique,
1111 StartingByte.QuadPart,
1115 try_return( ntStatus);
1120 // As per the read path -
1123 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1124 AFS_TRACE_LEVEL_VERBOSE,
1125 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1126 pFcb->ObjectInformation->FileId.Cell,
1127 pFcb->ObjectInformation->FileId.Volume,
1128 pFcb->ObjectInformation->FileId.Vnode,
1129 pFcb->ObjectInformation->FileId.Unique,
1130 StartingByte.QuadPart,
1133 ntStatus = AFSGetExtents( pFcb,
1140 if (!NT_SUCCESS(ntStatus))
1143 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1144 AFS_TRACE_LEVEL_ERROR,
1145 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1149 try_return( ntStatus );
1152 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1153 AFS_TRACE_LEVEL_VERBOSE,
1154 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1159 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1162 Irp->IoStatus.Information = ByteCount;
1166 // Setup the MD5 for each extent
1169 AFSSetupMD5Hash( pFcb,
1177 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1183 if (!NT_SUCCESS(ntStatus))
1186 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1187 AFS_TRACE_LEVEL_ERROR,
1188 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1193 try_return( ntStatus);
1197 // Retrieve the cache file object
1200 pCacheFileObject = AFSReferenceCacheFileObject();
1202 if( pCacheFileObject == NULL)
1205 ntStatus = STATUS_DEVICE_NOT_READY;
1207 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1208 AFS_TRACE_LEVEL_ERROR,
1209 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1210 pFcb->ObjectInformation->FileId.Cell,
1211 pFcb->ObjectInformation->FileId.Volume,
1212 pFcb->ObjectInformation->FileId.Vnode,
1213 pFcb->ObjectInformation->FileId.Unique,
1214 StartingByte.QuadPart,
1218 try_return( ntStatus);
1221 if (runCount > AFS_MAX_STACK_IO_RUNS)
1224 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1225 runCount * sizeof( AFSIoRun ),
1227 if (NULL == pIoRuns)
1230 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1231 AFS_TRACE_LEVEL_ERROR,
1232 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1235 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1244 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1246 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1255 if (!NT_SUCCESS(ntStatus))
1258 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1259 AFS_TRACE_LEVEL_ERROR,
1260 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1264 try_return( ntStatus );
1267 AFSReferenceActiveExtents( pStartExtent,
1270 bDerefExtents = TRUE;
1272 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1273 AFS_TRACE_LEVEL_VERBOSE,
1274 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1275 &pFcb->NPFcb->Specific.File.ExtentsResource,
1276 PsGetCurrentThread()));
1278 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1281 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1282 sizeof( AFSGatherIo),
1285 if (NULL == pGatherIo)
1288 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1289 AFS_TRACE_LEVEL_ERROR,
1290 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1293 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1294 AFS_TRACE_LEVEL_VERBOSE,
1295 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1296 &pFcb->NPFcb->Specific.File.ExtentsResource,
1297 PsGetCurrentThread()));
1299 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1303 AFSDereferenceActiveExtents( pStartExtent,
1306 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1309 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1312 // Initialize count to 1, that was we won't get an early
1313 // completion if the first irp completes before the second is
1316 pGatherIo->Count = 1;
1317 pGatherIo->Status = STATUS_SUCCESS;
1318 pGatherIo->MasterIrp = Irp;
1319 pGatherIo->Synchronous = TRUE;
1320 pGatherIo->CompleteMasterIrp = FALSE;
1322 bCompleteIrp = TRUE;
1324 if( pGatherIo->Synchronous)
1326 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1331 // Setup the MD5 for each extent
1334 AFSSetupMD5Hash( pFcb,
1343 // Pre-emptively set up the count
1346 Irp->IoStatus.Information = ByteCount;
1348 ntStatus = AFSQueueStartIos( pCacheFileObject,
1350 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1355 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1356 AFS_TRACE_LEVEL_VERBOSE,
1357 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1361 if( !NT_SUCCESS( ntStatus))
1364 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1365 AFS_TRACE_LEVEL_VERBOSE,
1366 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1367 &pFcb->NPFcb->Specific.File.ExtentsResource,
1368 PsGetCurrentThread()));
1370 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1374 AFSDereferenceActiveExtents( pStartExtent,
1377 try_return( ntStatus);
1381 // Wait for completion of All IOs we started.
1384 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1390 if( NT_SUCCESS( ntStatus))
1393 ntStatus = pGatherIo->Status;
1396 if( !NT_SUCCESS( ntStatus))
1399 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1400 AFS_TRACE_LEVEL_VERBOSE,
1401 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1402 &pFcb->NPFcb->Specific.File.ExtentsResource,
1403 PsGetCurrentThread()));
1405 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1409 AFSDereferenceActiveExtents( pStartExtent,
1412 try_return( ntStatus);
1417 if( NT_SUCCESS( ntStatus) &&
1418 pStartExtent != NULL &&
1419 Irp->IoStatus.Information > 0)
1425 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1431 // Since this is dirty we can mark the extents dirty now.
1432 // AFSMarkDirty will dereference the extents. Do not call
1433 // AFSDereferenceActiveExtents() in this code path.
1445 // This was an uncached user write - tell the server to do
1446 // the flush when the worker thread next wakes up
1448 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1452 if( pCacheFileObject != NULL)
1454 AFSReleaseCacheFileObject( pCacheFileObject);
1457 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1458 AFS_TRACE_LEVEL_VERBOSE,
1459 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1461 StartingByte.HighPart,
1462 StartingByte.LowPart,
1466 if (NT_SUCCESS(ntStatus) &&
1471 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1477 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1478 AFS_TRACE_LEVEL_VERBOSE,
1479 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1480 &pFcb->NPFcb->Specific.File.ExtentsResource,
1481 PsGetCurrentThread()));
1483 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1488 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1491 if( NULL != pIoRuns &&
1492 stIoRuns != pIoRuns)
1494 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1500 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1501 AFS_TRACE_LEVEL_VERBOSE,
1502 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1505 Irp->IoStatus.Information));
1507 AFSCompleteRequest( Irp, ntStatus);
1516 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1518 IN LARGE_INTEGER StartingByte,
1521 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1522 VOID *pSystemBuffer = NULL;
1523 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1524 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1525 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1526 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1527 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1528 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1529 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1530 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1531 AFSFileIOCB stFileIORequest;
1532 AFSFileIOResultCB stFileIOResult;
1533 ULONG ulResultLen = 0;
1538 Irp->IoStatus.Information = 0;
1540 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1541 AFS_TRACE_LEVEL_VERBOSE,
1542 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1544 StartingByte.HighPart,
1545 StartingByte.LowPart,
1548 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1551 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1552 AFS_TRACE_LEVEL_ERROR,
1553 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1556 pIrpSp->Parameters.Write.Length,
1557 pDevExt->Specific.RDR.MaxIo.QuadPart));
1559 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1563 // Get the mapping for the buffer
1565 pSystemBuffer = AFSLockSystemBuffer( Irp,
1568 if( pSystemBuffer == NULL)
1571 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1572 AFS_TRACE_LEVEL_ERROR,
1573 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1576 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1580 // Issue the request at the service for processing
1583 ulResultLen = sizeof( AFSFileIOResultCB);
1585 RtlZeroMemory( &stFileIORequest,
1586 sizeof( AFSFileIOCB));
1588 RtlZeroMemory( &stFileIOResult,
1589 sizeof( AFSFileIOResultCB));
1591 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1593 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1595 stFileIORequest.IOLength = ByteCount;
1597 stFileIORequest.IOOffset = StartingByte;
1599 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1601 if ( bNoIntermediateBuffering)
1604 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1608 // Update file metadata
1611 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1613 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1615 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1617 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1619 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1622 // Write the data to the service
1625 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1628 &pCcb->DirectoryCB->NameInformation.FileName,
1629 &pFcb->ObjectInformation->FileId,
1630 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1631 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1633 sizeof( AFSFileIOCB),
1637 if( NT_SUCCESS( ntStatus))
1640 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1645 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1646 AFS_TRACE_LEVEL_ERROR,
1647 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1654 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1655 AFS_TRACE_LEVEL_VERBOSE,
1656 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1658 StartingByte.HighPart,
1659 StartingByte.LowPart,
1663 if (NT_SUCCESS(ntStatus) &&
1668 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1671 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1672 AFS_TRACE_LEVEL_VERBOSE,
1673 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1676 Irp->IoStatus.Information));
1678 AFSCompleteRequest( Irp, ntStatus);
1686 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1688 IN LARGE_INTEGER StartingByte,
1690 IN BOOLEAN ForceFlush)
1692 UNREFERENCED_PARAMETER(DeviceObject);
1693 PVOID pSystemBuffer = NULL;
1694 NTSTATUS ntStatus = STATUS_SUCCESS;
1695 IO_STATUS_BLOCK iosbFlush;
1696 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1697 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1698 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1699 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1700 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1701 PMDL pCurrentMdl = Irp->MdlAddress;
1702 LARGE_INTEGER liCurrentOffset;
1707 Irp->IoStatus.Information = 0;
1709 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1715 CcPrepareMdlWrite( pFileObject,
1721 ntStatus = Irp->IoStatus.Status;
1723 __except( EXCEPTION_EXECUTE_HANDLER)
1725 ntStatus = GetExceptionCode();
1727 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1728 AFS_TRACE_LEVEL_ERROR,
1729 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1734 if( !NT_SUCCESS( ntStatus))
1738 // Free up any potentially allocated mdl's
1741 CcMdlWriteComplete( pFileObject,
1745 Irp->MdlAddress = NULL;
1747 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1748 AFS_TRACE_LEVEL_ERROR,
1749 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1754 try_return( ntStatus);
1757 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1759 while( ulTotalLen > 0)
1762 ntStatus = STATUS_SUCCESS;
1764 if( pCurrentMdl != NULL)
1767 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1768 NormalPagePriority);
1770 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1772 if( ulCurrentIO > ulTotalLen)
1774 ulCurrentIO = ulTotalLen;
1780 pSystemBuffer = AFSLockSystemBuffer( Irp,
1783 ulCurrentIO = ulTotalLen;
1786 if( pSystemBuffer == NULL)
1789 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1790 AFS_TRACE_LEVEL_ERROR,
1791 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1794 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1800 if( !CcCopyWrite( pFileObject,
1807 // Failed to process request.
1810 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1811 AFS_TRACE_LEVEL_ERROR,
1812 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1814 &pFileObject->FileName,
1815 liCurrentOffset.QuadPart,
1816 Irp->IoStatus.Status));
1818 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1821 __except( EXCEPTION_EXECUTE_HANDLER)
1824 ntStatus = GetExceptionCode();
1826 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1827 AFS_TRACE_LEVEL_ERROR,
1828 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1830 &pFileObject->FileName,
1831 liCurrentOffset.QuadPart,
1835 if( !NT_SUCCESS( ntStatus))
1837 try_return( ntStatus);
1841 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1845 // We have detected a file we do a write through with.
1848 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1853 if( !NT_SUCCESS( iosbFlush.Status))
1856 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1857 AFS_TRACE_LEVEL_ERROR,
1858 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1860 &pFileObject->FileName,
1861 pFcb->ObjectInformation->FileId.Cell,
1862 pFcb->ObjectInformation->FileId.Volume,
1863 pFcb->ObjectInformation->FileId.Vnode,
1864 pFcb->ObjectInformation->FileId.Unique,
1866 iosbFlush.Information));
1868 try_return( ntStatus = iosbFlush.Status);
1872 if( ulTotalLen <= ulCurrentIO)
1877 liCurrentOffset.QuadPart += ulCurrentIO;
1879 ulTotalLen -= ulCurrentIO;
1881 pCurrentMdl = pCurrentMdl->Next;
1886 if( NT_SUCCESS( ntStatus))
1889 Irp->IoStatus.Information = ByteCount;
1894 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1898 // If this extended the Vdl, then update it accordingly
1901 if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1904 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1908 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1911 // Write through asked for... Set things so that we get
1912 // flush when the worker thread next wakes up
1914 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1917 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1920 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1922 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1926 AFSCompleteRequest( Irp,
1935 AFSExtendingWrite( IN AFSFcb *Fcb,
1936 IN PFILE_OBJECT FileObject,
1937 IN LONGLONG NewLength)
1939 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1940 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1941 NTSTATUS ntStatus = STATUS_SUCCESS;
1942 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
1944 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1947 Fcb->Header.AllocationSize.QuadPart = NewLength;
1949 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1952 if( NewLength > Fcb->Header.FileSize.QuadPart)
1955 Fcb->Header.FileSize.QuadPart = NewLength;
1957 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1964 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
1965 Fcb->ObjectInformation,
1968 if (NT_SUCCESS(ntStatus))
1971 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1973 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1976 // If the file is currently cached, then let the MM know about the extension
1979 if( CcIsFileCached( FileObject))
1981 CcSetFileSizes( FileObject,
1982 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1987 Fcb->Header.FileSize = liSaveFileSize;
1988 Fcb->Header.AllocationSize = liSaveAllocation;
1992 // DownConvert file resource to shared
1994 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2000 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2004 UNREFERENCED_PARAMETER(DeviceObject);
2005 NTSTATUS ntStatus = STATUS_SUCCESS;
2006 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2007 AFSFcb *pFcb = NULL;
2008 AFSCcb *pCcb = NULL;
2009 AFSPipeIORequestCB *pIoRequest = NULL;
2010 void *pBuffer = NULL;
2011 AFSPipeIOResultCB stIoResult;
2012 ULONG ulBytesReturned = 0;
2017 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2019 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2021 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2022 AFS_TRACE_LEVEL_VERBOSE,
2023 "AFSShareWrite On pipe %wZ Length %08lX\n",
2024 &pCcb->DirectoryCB->NameInformation.FileName,
2025 pIrpSp->Parameters.Write.Length));
2027 if( pIrpSp->Parameters.Write.Length == 0)
2031 // Nothing to do in this case
2034 try_return( ntStatus);
2038 // Retrieve the buffer for the read request
2041 pBuffer = AFSLockSystemBuffer( Irp,
2042 pIrpSp->Parameters.Write.Length);
2044 if( pBuffer == NULL)
2047 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2048 AFS_TRACE_LEVEL_ERROR,
2049 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2050 &pCcb->DirectoryCB->NameInformation.FileName));
2052 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2055 AFSAcquireShared( &pFcb->NPFcb->Resource,
2058 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2059 sizeof( AFSPipeIORequestCB) +
2060 pIrpSp->Parameters.Write.Length,
2061 AFS_GENERIC_MEMORY_14_TAG);
2063 if( pIoRequest == NULL)
2066 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2069 RtlZeroMemory( pIoRequest,
2070 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2072 pIoRequest->RequestId = pCcb->RequestID;
2074 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2076 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2078 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2080 pIrpSp->Parameters.Write.Length);
2082 stIoResult.BytesProcessed = 0;
2084 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2087 // Issue the open request to the service
2090 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2091 AFS_REQUEST_FLAG_SYNCHRONOUS,
2093 &pCcb->DirectoryCB->NameInformation.FileName,
2098 sizeof( AFSPipeIORequestCB) +
2099 pIrpSp->Parameters.Write.Length,
2103 if( !NT_SUCCESS( ntStatus))
2106 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2107 AFS_TRACE_LEVEL_ERROR,
2108 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2112 try_return( ntStatus);
2115 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2116 AFS_TRACE_LEVEL_VERBOSE,
2117 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2118 &pCcb->DirectoryCB->NameInformation.FileName,
2119 stIoResult.BytesProcessed));
2121 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2128 AFSReleaseResource( &pFcb->NPFcb->Resource);
2131 if( pIoRequest != NULL)
2134 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);