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);
672 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
673 AFS_TRACE_LEVEL_VERBOSE,
674 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
676 liStartingByte.QuadPart,
678 bRetry ? " RETRY" : ""));
680 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
683 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
687 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
693 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
694 AFS_TRACE_LEVEL_VERBOSE,
695 "AFSCommonWrite (%p) Process complete Status %08lX\n",
699 ObDereferenceObject(pFileObject);
701 if( bReleaseSectionObject)
704 AFSReleaseResource( &pNPFcb->SectionObjectResource);
710 AFSReleaseResource( &pNPFcb->PagingResource);
716 AFSReleaseResource( &pNPFcb->Resource);
722 AFSCompleteRequest( Irp,
731 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
735 UNREFERENCED_PARAMETER(DeviceObject);
736 NTSTATUS ntStatus = STATUS_SUCCESS;
737 AFSPIOCtlIORequestCB stIORequestCB;
738 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
741 AFSPIOCtlIOResultCB stIOResultCB;
742 ULONG ulBytesReturned = 0;
743 AFSFileID stParentFID;
748 Irp->IoStatus.Information = 0;
750 RtlZeroMemory( &stIORequestCB,
751 sizeof( AFSPIOCtlIORequestCB));
753 if( pIrpSp->Parameters.Write.Length == 0)
757 // Nothing to do in this case
760 try_return( ntStatus);
763 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
765 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
767 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
768 AFS_TRACE_LEVEL_VERBOSE,
769 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
770 &pFcb->NPFcb->Resource,
771 PsGetCurrentThread()));
773 AFSAcquireShared( &pFcb->NPFcb->Resource,
777 // Get the parent fid to pass to the cm
780 RtlZeroMemory( &stParentFID,
783 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
787 // The parent directory FID of the node
790 stParentFID = pFcb->ObjectInformation->ParentFileId;
794 // Set the control block up
797 stIORequestCB.RequestId = pCcb->RequestID;
799 if( pFcb->ObjectInformation->VolumeCB != NULL)
801 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
805 // Lock down the buffer
808 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
809 pIrpSp->Parameters.Write.Length);
811 if( stIORequestCB.MappedBuffer == NULL)
814 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
817 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
819 stIOResultCB.BytesProcessed = 0;
821 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
824 // Issue the request to the service
827 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
828 AFS_REQUEST_FLAG_SYNCHRONOUS,
834 (void *)&stIORequestCB,
835 sizeof( AFSPIOCtlIORequestCB),
839 if( !NT_SUCCESS( ntStatus))
842 try_return( ntStatus);
846 // Update the length written
849 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
853 if( stIORequestCB.MappedBuffer != NULL)
856 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
863 AFSReleaseResource( &pFcb->NPFcb->Resource);
871 // This function is called when we know we have to read from the AFS Cache.
873 // It ensures that we have exents for the entirety of the write and
874 // then pins the extents into memory (meaning that although we may
875 // add we will not remove). Then it creates a scatter gather write
876 // and fires off the IRPs
880 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
882 IN LARGE_INTEGER StartingByte,
885 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
886 VOID *pSystemBuffer = NULL;
887 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
888 BOOLEAN bLocked = FALSE;
889 BOOLEAN bCompleteIrp = TRUE;
890 AFSGatherIo *pGatherIo = NULL;
891 AFSIoRun *pIoRuns = NULL;
892 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
893 ULONG extentsCount = 0, runCount = 0;
894 AFSExtent *pStartExtent = NULL;
895 AFSExtent *pIgnoreExtent = NULL;
896 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
897 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
898 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
899 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
900 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
901 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
902 LARGE_INTEGER liCurrentTime, liLastRequestTime;
903 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
904 PFILE_OBJECT pCacheFileObject = NULL;
905 BOOLEAN bDerefExtents = FALSE;
910 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
911 AFS_TRACE_LEVEL_VERBOSE,
912 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
914 StartingByte.HighPart,
915 StartingByte.LowPart,
918 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
921 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
922 AFS_TRACE_LEVEL_ERROR,
923 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
926 pIrpSp->Parameters.Write.Length,
927 pDevExt->Specific.RDR.MaxIo.QuadPart));
929 try_return( ntStatus = STATUS_UNSUCCESSFUL);
933 // Get the mapping for the buffer
935 pSystemBuffer = AFSLockSystemBuffer( Irp,
938 if( pSystemBuffer == NULL)
941 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
942 AFS_TRACE_LEVEL_ERROR,
943 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
946 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
951 // Provoke a get of the extents - if we need to.
954 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
955 AFS_TRACE_LEVEL_VERBOSE,
956 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
957 pFcb->ObjectInformation->FileId.Cell,
958 pFcb->ObjectInformation->FileId.Volume,
959 pFcb->ObjectInformation->FileId.Vnode,
960 pFcb->ObjectInformation->FileId.Unique,
961 StartingByte.QuadPart,
964 ntStatus = AFSRequestExtentsAsync( pFcb,
969 if (!NT_SUCCESS(ntStatus))
972 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
973 AFS_TRACE_LEVEL_ERROR,
974 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
978 try_return( ntStatus);
981 KeQueryTickCount( &liLastRequestTime);
986 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
987 AFS_TRACE_LEVEL_VERBOSE,
988 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
989 &pFcb->NPFcb->Specific.File.ExtentsResource,
990 PsGetCurrentThread()));
992 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
994 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
998 pIgnoreExtent = NULL;
1000 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1005 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1007 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1008 AFS_TRACE_LEVEL_VERBOSE,
1009 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1010 &pFcb->NPFcb->Specific.File.ExtentsResource,
1011 PsGetCurrentThread()));
1013 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1017 // We will re-request the extents after waiting for them
1020 KeQueryTickCount( &liCurrentTime);
1022 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1025 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1026 AFS_TRACE_LEVEL_VERBOSE,
1027 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1028 pFcb->ObjectInformation->FileId.Cell,
1029 pFcb->ObjectInformation->FileId.Volume,
1030 pFcb->ObjectInformation->FileId.Vnode,
1031 pFcb->ObjectInformation->FileId.Unique,
1032 StartingByte.QuadPart,
1035 ntStatus = AFSRequestExtentsAsync( pFcb,
1040 if (!NT_SUCCESS(ntStatus))
1043 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1044 AFS_TRACE_LEVEL_ERROR,
1045 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1049 try_return( ntStatus);
1052 KeQueryTickCount( &liLastRequestTime);
1056 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1057 AFS_TRACE_LEVEL_VERBOSE,
1058 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1059 pFcb->ObjectInformation->FileId.Cell,
1060 pFcb->ObjectInformation->FileId.Volume,
1061 pFcb->ObjectInformation->FileId.Vnode,
1062 pFcb->ObjectInformation->FileId.Unique,
1063 StartingByte.QuadPart,
1070 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1072 if (!NT_SUCCESS(ntStatus))
1075 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1076 AFS_TRACE_LEVEL_ERROR,
1077 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1078 pFcb->ObjectInformation->FileId.Cell,
1079 pFcb->ObjectInformation->FileId.Volume,
1080 pFcb->ObjectInformation->FileId.Vnode,
1081 pFcb->ObjectInformation->FileId.Unique,
1082 StartingByte.QuadPart,
1086 try_return( ntStatus);
1091 // As per the read path -
1094 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1095 AFS_TRACE_LEVEL_VERBOSE,
1096 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1097 pFcb->ObjectInformation->FileId.Cell,
1098 pFcb->ObjectInformation->FileId.Volume,
1099 pFcb->ObjectInformation->FileId.Vnode,
1100 pFcb->ObjectInformation->FileId.Unique,
1101 StartingByte.QuadPart,
1104 ntStatus = AFSGetExtents( pFcb,
1111 if (!NT_SUCCESS(ntStatus))
1114 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1115 AFS_TRACE_LEVEL_ERROR,
1116 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1120 try_return( ntStatus );
1123 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1124 AFS_TRACE_LEVEL_VERBOSE,
1125 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1130 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1133 Irp->IoStatus.Information = ByteCount;
1137 // Setup the MD5 for each extent
1140 AFSSetupMD5Hash( pFcb,
1148 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1154 if (!NT_SUCCESS(ntStatus))
1157 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1158 AFS_TRACE_LEVEL_ERROR,
1159 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1164 try_return( ntStatus);
1168 // Retrieve the cache file object
1171 pCacheFileObject = AFSReferenceCacheFileObject();
1173 if( pCacheFileObject == NULL)
1176 ntStatus = STATUS_DEVICE_NOT_READY;
1178 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1179 AFS_TRACE_LEVEL_ERROR,
1180 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1181 pFcb->ObjectInformation->FileId.Cell,
1182 pFcb->ObjectInformation->FileId.Volume,
1183 pFcb->ObjectInformation->FileId.Vnode,
1184 pFcb->ObjectInformation->FileId.Unique,
1185 StartingByte.QuadPart,
1189 try_return( ntStatus);
1192 if (runCount > AFS_MAX_STACK_IO_RUNS)
1195 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1196 runCount * sizeof( AFSIoRun ),
1198 if (NULL == pIoRuns)
1201 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1202 AFS_TRACE_LEVEL_ERROR,
1203 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1206 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1215 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1217 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1226 if (!NT_SUCCESS(ntStatus))
1229 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1230 AFS_TRACE_LEVEL_ERROR,
1231 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1235 try_return( ntStatus );
1238 AFSReferenceActiveExtents( pStartExtent,
1241 bDerefExtents = TRUE;
1243 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1244 AFS_TRACE_LEVEL_VERBOSE,
1245 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1246 &pFcb->NPFcb->Specific.File.ExtentsResource,
1247 PsGetCurrentThread()));
1249 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1252 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1253 sizeof( AFSGatherIo),
1256 if (NULL == pGatherIo)
1259 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1260 AFS_TRACE_LEVEL_ERROR,
1261 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1264 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1265 AFS_TRACE_LEVEL_VERBOSE,
1266 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1267 &pFcb->NPFcb->Specific.File.ExtentsResource,
1268 PsGetCurrentThread()));
1270 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1274 AFSDereferenceActiveExtents( pStartExtent,
1277 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1280 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1283 // Initialize count to 1, that was we won't get an early
1284 // completion if the first irp completes before the second is
1287 pGatherIo->Count = 1;
1288 pGatherIo->Status = STATUS_SUCCESS;
1289 pGatherIo->MasterIrp = Irp;
1290 pGatherIo->Synchronous = TRUE;
1291 pGatherIo->CompleteMasterIrp = FALSE;
1293 bCompleteIrp = TRUE;
1295 if( pGatherIo->Synchronous)
1297 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1302 // Setup the MD5 for each extent
1305 AFSSetupMD5Hash( pFcb,
1314 // Pre-emptively set up the count
1317 Irp->IoStatus.Information = ByteCount;
1319 ntStatus = AFSQueueStartIos( pCacheFileObject,
1321 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1326 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1327 AFS_TRACE_LEVEL_VERBOSE,
1328 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1332 if( !NT_SUCCESS( ntStatus))
1335 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1336 AFS_TRACE_LEVEL_VERBOSE,
1337 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1338 &pFcb->NPFcb->Specific.File.ExtentsResource,
1339 PsGetCurrentThread()));
1341 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1345 AFSDereferenceActiveExtents( pStartExtent,
1348 try_return( ntStatus);
1352 // Wait for completion of All IOs we started.
1355 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1361 if( NT_SUCCESS( ntStatus))
1364 ntStatus = pGatherIo->Status;
1367 if( !NT_SUCCESS( ntStatus))
1370 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1371 AFS_TRACE_LEVEL_VERBOSE,
1372 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1373 &pFcb->NPFcb->Specific.File.ExtentsResource,
1374 PsGetCurrentThread()));
1376 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1380 AFSDereferenceActiveExtents( pStartExtent,
1383 try_return( ntStatus);
1388 if( NT_SUCCESS( ntStatus) &&
1389 pStartExtent != NULL &&
1390 Irp->IoStatus.Information > 0)
1396 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1402 // Since this is dirty we can mark the extents dirty now.
1403 // AFSMarkDirty will dereference the extents. Do not call
1404 // AFSDereferenceActiveExtents() in this code path.
1416 // This was an uncached user write - tell the server to do
1417 // the flush when the worker thread next wakes up
1419 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1423 if( pCacheFileObject != NULL)
1425 AFSReleaseCacheFileObject( pCacheFileObject);
1428 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1429 AFS_TRACE_LEVEL_VERBOSE,
1430 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1432 StartingByte.HighPart,
1433 StartingByte.LowPart,
1437 if (NT_SUCCESS(ntStatus) &&
1442 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1448 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1449 AFS_TRACE_LEVEL_VERBOSE,
1450 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1451 &pFcb->NPFcb->Specific.File.ExtentsResource,
1452 PsGetCurrentThread()));
1454 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1459 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1462 if( NULL != pIoRuns &&
1463 stIoRuns != pIoRuns)
1465 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1471 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1472 AFS_TRACE_LEVEL_VERBOSE,
1473 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1476 Irp->IoStatus.Information));
1478 AFSCompleteRequest( Irp, ntStatus);
1487 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1489 IN LARGE_INTEGER StartingByte,
1492 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1493 VOID *pSystemBuffer = NULL;
1494 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1495 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1496 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1497 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1498 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1499 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1500 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1501 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1502 AFSFileIOCB stFileIORequest;
1503 AFSFileIOResultCB stFileIOResult;
1504 ULONG ulResultLen = 0;
1509 Irp->IoStatus.Information = 0;
1511 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1512 AFS_TRACE_LEVEL_VERBOSE,
1513 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1515 StartingByte.HighPart,
1516 StartingByte.LowPart,
1519 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1522 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1523 AFS_TRACE_LEVEL_ERROR,
1524 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1527 pIrpSp->Parameters.Write.Length,
1528 pDevExt->Specific.RDR.MaxIo.QuadPart));
1530 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1534 // Get the mapping for the buffer
1536 pSystemBuffer = AFSLockSystemBuffer( Irp,
1539 if( pSystemBuffer == NULL)
1542 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1543 AFS_TRACE_LEVEL_ERROR,
1544 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1547 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1551 // Issue the request at the service for processing
1554 ulResultLen = sizeof( AFSFileIOResultCB);
1556 RtlZeroMemory( &stFileIORequest,
1557 sizeof( AFSFileIOCB));
1559 RtlZeroMemory( &stFileIOResult,
1560 sizeof( AFSFileIOResultCB));
1562 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1564 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1566 stFileIORequest.IOLength = ByteCount;
1568 stFileIORequest.IOOffset = StartingByte;
1570 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1572 if ( bNoIntermediateBuffering)
1575 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1579 // Update file metadata
1582 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1584 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1586 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1588 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1590 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1593 // Write the data to the service
1596 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1599 &pCcb->DirectoryCB->NameInformation.FileName,
1600 &pFcb->ObjectInformation->FileId,
1601 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1602 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1604 sizeof( AFSFileIOCB),
1608 if( NT_SUCCESS( ntStatus))
1611 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1616 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1617 AFS_TRACE_LEVEL_ERROR,
1618 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1625 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1626 AFS_TRACE_LEVEL_VERBOSE,
1627 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1629 StartingByte.HighPart,
1630 StartingByte.LowPart,
1634 if (NT_SUCCESS(ntStatus) &&
1639 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1642 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1643 AFS_TRACE_LEVEL_VERBOSE,
1644 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1647 Irp->IoStatus.Information));
1649 AFSCompleteRequest( Irp, ntStatus);
1657 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1659 IN LARGE_INTEGER StartingByte,
1661 IN BOOLEAN ForceFlush)
1663 UNREFERENCED_PARAMETER(DeviceObject);
1664 PVOID pSystemBuffer = NULL;
1665 NTSTATUS ntStatus = STATUS_SUCCESS;
1666 IO_STATUS_BLOCK iosbFlush;
1667 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1668 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1669 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1670 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1671 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1672 PMDL pCurrentMdl = Irp->MdlAddress;
1673 LARGE_INTEGER liCurrentOffset;
1678 Irp->IoStatus.Information = 0;
1680 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1686 CcPrepareMdlWrite( pFileObject,
1692 ntStatus = Irp->IoStatus.Status;
1694 __except( EXCEPTION_EXECUTE_HANDLER)
1696 ntStatus = GetExceptionCode();
1698 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1699 AFS_TRACE_LEVEL_ERROR,
1700 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1705 if( !NT_SUCCESS( ntStatus))
1709 // Free up any potentially allocated mdl's
1712 CcMdlWriteComplete( pFileObject,
1716 Irp->MdlAddress = NULL;
1718 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1719 AFS_TRACE_LEVEL_ERROR,
1720 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1725 try_return( ntStatus);
1728 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1730 while( ulTotalLen > 0)
1733 ntStatus = STATUS_SUCCESS;
1735 if( pCurrentMdl != NULL)
1738 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1739 NormalPagePriority);
1741 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1743 if( ulCurrentIO > ulTotalLen)
1745 ulCurrentIO = ulTotalLen;
1751 pSystemBuffer = AFSLockSystemBuffer( Irp,
1754 ulCurrentIO = ulTotalLen;
1757 if( pSystemBuffer == NULL)
1760 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1761 AFS_TRACE_LEVEL_ERROR,
1762 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1765 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1771 if( !CcCopyWrite( pFileObject,
1778 // Failed to process request.
1781 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1782 AFS_TRACE_LEVEL_ERROR,
1783 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1785 &pFileObject->FileName,
1786 liCurrentOffset.QuadPart,
1787 Irp->IoStatus.Status));
1789 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1792 __except( EXCEPTION_EXECUTE_HANDLER)
1795 ntStatus = GetExceptionCode();
1797 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1798 AFS_TRACE_LEVEL_ERROR,
1799 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1801 &pFileObject->FileName,
1802 liCurrentOffset.QuadPart,
1806 if( !NT_SUCCESS( ntStatus))
1808 try_return( ntStatus);
1812 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1816 // We have detected a file we do a write through with.
1819 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1824 if( !NT_SUCCESS( iosbFlush.Status))
1827 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1828 AFS_TRACE_LEVEL_ERROR,
1829 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1831 &pFileObject->FileName,
1832 pFcb->ObjectInformation->FileId.Cell,
1833 pFcb->ObjectInformation->FileId.Volume,
1834 pFcb->ObjectInformation->FileId.Vnode,
1835 pFcb->ObjectInformation->FileId.Unique,
1837 iosbFlush.Information));
1839 try_return( ntStatus = iosbFlush.Status);
1843 if( ulTotalLen <= ulCurrentIO)
1848 liCurrentOffset.QuadPart += ulCurrentIO;
1850 ulTotalLen -= ulCurrentIO;
1852 pCurrentMdl = pCurrentMdl->Next;
1857 if( NT_SUCCESS( ntStatus))
1860 Irp->IoStatus.Information = ByteCount;
1865 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1869 // If this extended the Vdl, then update it accordingly
1872 if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1875 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1879 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1882 // Write through asked for... Set things so that we get
1883 // flush when the worker thread next wakes up
1885 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1888 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1891 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1893 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1897 AFSCompleteRequest( Irp,
1906 AFSExtendingWrite( IN AFSFcb *Fcb,
1907 IN PFILE_OBJECT FileObject,
1908 IN LONGLONG NewLength)
1910 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1911 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1912 NTSTATUS ntStatus = STATUS_SUCCESS;
1913 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
1915 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1918 Fcb->Header.AllocationSize.QuadPart = NewLength;
1920 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1923 if( NewLength > Fcb->Header.FileSize.QuadPart)
1926 Fcb->Header.FileSize.QuadPart = NewLength;
1928 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1935 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
1936 Fcb->ObjectInformation,
1939 if (NT_SUCCESS(ntStatus))
1942 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1944 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1947 // If the file is currently cached, then let the MM know about the extension
1950 if( CcIsFileCached( FileObject))
1952 CcSetFileSizes( FileObject,
1953 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1958 Fcb->Header.FileSize = liSaveFileSize;
1959 Fcb->Header.AllocationSize = liSaveAllocation;
1963 // DownConvert file resource to shared
1965 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
1971 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
1975 UNREFERENCED_PARAMETER(DeviceObject);
1976 NTSTATUS ntStatus = STATUS_SUCCESS;
1977 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1978 AFSFcb *pFcb = NULL;
1979 AFSCcb *pCcb = NULL;
1980 AFSPipeIORequestCB *pIoRequest = NULL;
1981 void *pBuffer = NULL;
1982 AFSPipeIOResultCB stIoResult;
1983 ULONG ulBytesReturned = 0;
1988 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1990 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1992 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1993 AFS_TRACE_LEVEL_VERBOSE,
1994 "AFSShareWrite On pipe %wZ Length %08lX\n",
1995 &pCcb->DirectoryCB->NameInformation.FileName,
1996 pIrpSp->Parameters.Write.Length));
1998 if( pIrpSp->Parameters.Write.Length == 0)
2002 // Nothing to do in this case
2005 try_return( ntStatus);
2009 // Retrieve the buffer for the read request
2012 pBuffer = AFSLockSystemBuffer( Irp,
2013 pIrpSp->Parameters.Write.Length);
2015 if( pBuffer == NULL)
2018 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2019 AFS_TRACE_LEVEL_ERROR,
2020 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2021 &pCcb->DirectoryCB->NameInformation.FileName));
2023 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2026 AFSAcquireShared( &pFcb->NPFcb->Resource,
2029 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2030 sizeof( AFSPipeIORequestCB) +
2031 pIrpSp->Parameters.Write.Length,
2032 AFS_GENERIC_MEMORY_14_TAG);
2034 if( pIoRequest == NULL)
2037 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2040 RtlZeroMemory( pIoRequest,
2041 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2043 pIoRequest->RequestId = pCcb->RequestID;
2045 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2047 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2049 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2051 pIrpSp->Parameters.Write.Length);
2053 stIoResult.BytesProcessed = 0;
2055 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2058 // Issue the open request to the service
2061 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2062 AFS_REQUEST_FLAG_SYNCHRONOUS,
2064 &pCcb->DirectoryCB->NameInformation.FileName,
2069 sizeof( AFSPipeIORequestCB) +
2070 pIrpSp->Parameters.Write.Length,
2074 if( !NT_SUCCESS( ntStatus))
2077 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2078 AFS_TRACE_LEVEL_ERROR,
2079 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2083 try_return( ntStatus);
2086 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2087 AFS_TRACE_LEVEL_VERBOSE,
2088 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2089 &pCcb->DirectoryCB->NameInformation.FileName,
2090 stIoResult.BytesProcessed));
2092 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2099 AFSReleaseResource( &pFcb->NPFcb->Resource);
2102 if( pIoRequest != NULL)
2105 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);