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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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.Characteristics, FILE_READ_ONLY_DEVICE))
253 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
393 AFS_TRACE_LEVEL_ERROR,
394 "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
399 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1289 AFS_TRACE_LEVEL_ERROR,
1290 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1293 AFSDbgLogMsg( 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 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1356 AFS_TRACE_LEVEL_VERBOSE,
1357 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1361 if( !NT_SUCCESS( ntStatus))
1364 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1646 AFS_TRACE_LEVEL_ERROR,
1647 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1655 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1656 AFS_TRACE_LEVEL_VERBOSE,
1657 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1659 StartingByte.HighPart,
1660 StartingByte.LowPart,
1664 if (NT_SUCCESS(ntStatus) &&
1669 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1672 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1673 AFS_TRACE_LEVEL_VERBOSE,
1674 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1677 Irp->IoStatus.Information);
1679 AFSCompleteRequest( Irp, ntStatus);
1687 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1689 IN LARGE_INTEGER StartingByte,
1691 IN BOOLEAN ForceFlush)
1693 UNREFERENCED_PARAMETER(DeviceObject);
1694 PVOID pSystemBuffer = NULL;
1695 NTSTATUS ntStatus = STATUS_SUCCESS;
1696 IO_STATUS_BLOCK iosbFlush;
1697 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1698 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1699 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1700 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1701 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1702 PMDL pCurrentMdl = Irp->MdlAddress;
1703 LARGE_INTEGER liCurrentOffset;
1708 Irp->IoStatus.Information = 0;
1710 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1716 CcPrepareMdlWrite( pFileObject,
1722 ntStatus = Irp->IoStatus.Status;
1724 __except( EXCEPTION_EXECUTE_HANDLER)
1726 ntStatus = GetExceptionCode();
1728 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1729 AFS_TRACE_LEVEL_ERROR,
1730 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1735 if( !NT_SUCCESS( ntStatus))
1739 // Free up any potentially allocated mdl's
1742 CcMdlWriteComplete( pFileObject,
1746 Irp->MdlAddress = NULL;
1748 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1749 AFS_TRACE_LEVEL_ERROR,
1750 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1755 try_return( ntStatus);
1758 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1760 while( ulTotalLen > 0)
1763 ntStatus = STATUS_SUCCESS;
1765 if( pCurrentMdl != NULL)
1768 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1769 NormalPagePriority);
1771 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1773 if( ulCurrentIO > ulTotalLen)
1775 ulCurrentIO = ulTotalLen;
1781 pSystemBuffer = AFSLockSystemBuffer( Irp,
1784 ulCurrentIO = ulTotalLen;
1787 if( pSystemBuffer == NULL)
1790 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1791 AFS_TRACE_LEVEL_ERROR,
1792 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1795 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1801 if( !CcCopyWrite( pFileObject,
1808 // Failed to process request.
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812 AFS_TRACE_LEVEL_ERROR,
1813 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1815 &pFileObject->FileName,
1816 liCurrentOffset.QuadPart,
1817 Irp->IoStatus.Status);
1819 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1822 __except( EXCEPTION_EXECUTE_HANDLER)
1825 ntStatus = GetExceptionCode();
1827 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1828 AFS_TRACE_LEVEL_ERROR,
1829 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1831 &pFileObject->FileName,
1832 liCurrentOffset.QuadPart,
1836 if( !NT_SUCCESS( ntStatus))
1838 try_return( ntStatus);
1842 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1846 // We have detected a file we do a write through with.
1849 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1854 if( !NT_SUCCESS( iosbFlush.Status))
1857 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1858 AFS_TRACE_LEVEL_ERROR,
1859 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1861 &pFileObject->FileName,
1862 pFcb->ObjectInformation->FileId.Cell,
1863 pFcb->ObjectInformation->FileId.Volume,
1864 pFcb->ObjectInformation->FileId.Vnode,
1865 pFcb->ObjectInformation->FileId.Unique,
1867 iosbFlush.Information);
1869 try_return( ntStatus = iosbFlush.Status);
1873 if( ulTotalLen <= ulCurrentIO)
1878 liCurrentOffset.QuadPart += ulCurrentIO;
1880 ulTotalLen -= ulCurrentIO;
1882 pCurrentMdl = pCurrentMdl->Next;
1887 if( NT_SUCCESS( ntStatus))
1890 Irp->IoStatus.Information = ByteCount;
1895 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1899 // If this extended the Vdl, then update it accordingly
1902 if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1905 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1909 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1912 // Write through asked for... Set things so that we get
1913 // flush when the worker thread next wakes up
1915 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1918 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1921 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1923 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1927 AFSCompleteRequest( Irp,
1936 AFSExtendingWrite( IN AFSFcb *Fcb,
1937 IN PFILE_OBJECT FileObject,
1938 IN LONGLONG NewLength)
1940 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1941 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1942 NTSTATUS ntStatus = STATUS_SUCCESS;
1943 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
1945 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1948 Fcb->Header.AllocationSize.QuadPart = NewLength;
1950 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1953 if( NewLength > Fcb->Header.FileSize.QuadPart)
1956 Fcb->Header.FileSize.QuadPart = NewLength;
1958 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1965 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
1966 Fcb->ObjectInformation,
1969 if (NT_SUCCESS(ntStatus))
1972 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1974 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1977 // If the file is currently cached, then let the MM know about the extension
1980 if( CcIsFileCached( FileObject))
1982 CcSetFileSizes( FileObject,
1983 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1988 Fcb->Header.FileSize = liSaveFileSize;
1989 Fcb->Header.AllocationSize = liSaveAllocation;
1993 // DownConvert file resource to shared
1995 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2001 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2005 UNREFERENCED_PARAMETER(DeviceObject);
2006 NTSTATUS ntStatus = STATUS_SUCCESS;
2007 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2008 AFSFcb *pFcb = NULL;
2009 AFSCcb *pCcb = NULL;
2010 AFSPipeIORequestCB *pIoRequest = NULL;
2011 void *pBuffer = NULL;
2012 AFSPipeIOResultCB stIoResult;
2013 ULONG ulBytesReturned = 0;
2018 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2020 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2022 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2023 AFS_TRACE_LEVEL_VERBOSE,
2024 "AFSShareWrite On pipe %wZ Length %08lX\n",
2025 &pCcb->DirectoryCB->NameInformation.FileName,
2026 pIrpSp->Parameters.Write.Length);
2028 if( pIrpSp->Parameters.Write.Length == 0)
2032 // Nothing to do in this case
2035 try_return( ntStatus);
2039 // Retrieve the buffer for the read request
2042 pBuffer = AFSLockSystemBuffer( Irp,
2043 pIrpSp->Parameters.Write.Length);
2045 if( pBuffer == NULL)
2048 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2049 AFS_TRACE_LEVEL_ERROR,
2050 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2051 &pCcb->DirectoryCB->NameInformation.FileName);
2053 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2056 AFSAcquireShared( &pFcb->NPFcb->Resource,
2059 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2060 sizeof( AFSPipeIORequestCB) +
2061 pIrpSp->Parameters.Write.Length,
2062 AFS_GENERIC_MEMORY_14_TAG);
2064 if( pIoRequest == NULL)
2067 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2070 RtlZeroMemory( pIoRequest,
2071 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2073 pIoRequest->RequestId = pCcb->RequestID;
2075 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2077 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2079 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2081 pIrpSp->Parameters.Write.Length);
2083 stIoResult.BytesProcessed = 0;
2085 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2088 // Issue the open request to the service
2091 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2092 AFS_REQUEST_FLAG_SYNCHRONOUS,
2094 &pCcb->DirectoryCB->NameInformation.FileName,
2099 sizeof( AFSPipeIORequestCB) +
2100 pIrpSp->Parameters.Write.Length,
2104 if( !NT_SUCCESS( ntStatus))
2107 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2108 AFS_TRACE_LEVEL_ERROR,
2109 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2113 try_return( ntStatus);
2116 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2117 AFS_TRACE_LEVEL_VERBOSE,
2118 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2119 &pCcb->DirectoryCB->NameInformation.FileName,
2120 stIoResult.BytesProcessed);
2122 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2129 AFSReleaseResource( &pFcb->NPFcb->Resource);
2132 if( pIoRequest != NULL)
2135 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);