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;
125 HANDLE hCallingUser = OnBehalfOf;
126 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
127 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
129 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
134 Irp->IoStatus.Information = 0;
136 pFileObject = pIrpSp->FileObject;
139 // Extract the fileobject references
142 pFcb = (AFSFcb *)pFileObject->FsContext;
143 pCcb = (AFSCcb *)pFileObject->FsContext2;
145 ObReferenceObject( pFileObject);
150 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
151 AFS_TRACE_LEVEL_ERROR,
152 "AFSCommonWrite Attempted write (%p) when pFcb == NULL\n",
155 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
158 pNPFcb = pFcb->NPFcb;
161 // If we are in shutdown mode then fail the request
164 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
167 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
168 AFS_TRACE_LEVEL_WARNING,
169 "AFSCommonWrite (%p) Open request after shutdown\n",
172 try_return( ntStatus = STATUS_TOO_LATE);
175 liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
176 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
177 bNonCachedIo = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
178 ulByteCount = pIrpSp->Parameters.Write.Length;
180 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
181 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
182 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
185 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
186 AFS_TRACE_LEVEL_ERROR,
187 "AFSCommonWrite Attempted write (%p) on an invalid node type %08lX\n",
189 pFcb->Header.NodeTypeCode);
191 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
195 // If this is a write against an IOCtl node then handle it
196 // in a different pathway
199 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
202 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
203 AFS_TRACE_LEVEL_VERBOSE,
204 "AFSCommonWrite (%p) Processing file (PIOCTL) Offset %0I64X Length %08lX Irp Flags %08lX\n",
206 liStartingByte.QuadPart,
210 ntStatus = AFSIOCtlWrite( DeviceObject,
213 try_return( ntStatus);
215 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
218 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
219 AFS_TRACE_LEVEL_VERBOSE,
220 "AFSCommonWrite (%p) Processing file (SHARE) Offset %0I64X Length %08lX Irp Flags %08lX\n",
222 liStartingByte.QuadPart,
226 ntStatus = AFSShareWrite( DeviceObject,
229 try_return( ntStatus);
233 // Is the Cache not there yet? Exit.
235 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
236 !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
237 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
240 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
241 AFS_TRACE_LEVEL_ERROR,
242 "AFSCommonWrite (%p) Request failed due to AFS cache closed\n",
245 try_return( ntStatus = STATUS_TOO_LATE );
248 if( pFcb->ObjectInformation->VolumeCB != NULL &&
249 BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.Characteristics, FILE_READ_ONLY_DEVICE))
252 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
253 AFS_TRACE_LEVEL_ERROR,
254 "AFSCommonWrite (%p) Request failed due to read only volume\n",
257 try_return( ntStatus = STATUS_ACCESS_DENIED);
261 // We need to know on whose behalf we have been called (which
262 // we will eventually tell to the server - for non paging
263 // writes). If we were posted then we were told. If this is
264 // the first time we saw the irp then we grab it now.
266 if( NULL == OnBehalfOf )
269 hCallingUser = PsGetCurrentProcessId();
274 hCallingUser = OnBehalfOf;
278 // Check for zero length write
281 if( ulByteCount == 0)
284 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
285 AFS_TRACE_LEVEL_VERBOSE,
286 "AFSCommonWrite (%p) Request completed due to zero length\n",
289 try_return( ntStatus);
293 // Is this Fcb valid???
296 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
299 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
300 AFS_TRACE_LEVEL_ERROR,
301 "AFSCommonWrite (%p) Failing request due to INVALID fcb\n",
304 try_return( ntStatus = STATUS_FILE_DELETED);
307 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
308 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
311 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
312 AFS_TRACE_LEVEL_ERROR,
313 "AFSCommonWrite (%p) Request failed due to file deleted\n",
316 try_return( ntStatus = STATUS_FILE_DELETED);
319 if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
322 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
323 AFS_TRACE_LEVEL_VERBOSE,
324 "AFSCommonWrite (%p) IRP_MN_COMPLETE being processed\n",
327 CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
330 // Mdl is now Deallocated
333 Irp->MdlAddress = NULL;
335 try_return( ntStatus = STATUS_SUCCESS );
339 // If we get a non cached IO for a cached file we should do a purge.
340 // For now we will just promote to cached
342 if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
344 bNonCachedIo = FALSE;
347 if ( !bNonCachedIo && !bPagingIo)
350 if( pFileObject->PrivateCacheMap == NULL)
353 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
354 AFS_TRACE_LEVEL_VERBOSE,
355 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
356 &pNPFcb->SectionObjectResource,
357 PsGetCurrentThread());
359 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
362 bReleaseSectionObject = TRUE;
367 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
368 AFS_TRACE_LEVEL_VERBOSE,
369 "AFSCommonWrite Initialize caching on Fcb %p FileObject %p\n",
373 CcInitializeCacheMap( pFileObject,
374 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
376 AFSLibCacheManagerCallbacks,
379 CcSetReadAheadGranularity( pFileObject,
380 pDeviceExt->Specific.RDR.MaximumRPCLength);
382 CcSetDirtyPageThreshold( pFileObject,
383 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
385 __except( EXCEPTION_EXECUTE_HANDLER)
388 ntStatus = GetExceptionCode();
390 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
391 AFS_TRACE_LEVEL_ERROR,
392 "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
397 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
398 AFS_TRACE_LEVEL_VERBOSE,
399 "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
400 &pNPFcb->SectionObjectResource,
401 PsGetCurrentThread());
403 AFSReleaseResource( &pNPFcb->SectionObjectResource);
405 bReleaseSectionObject = FALSE;
407 if( !NT_SUCCESS( ntStatus))
410 try_return( ntStatus);
414 if (!CcCanIWrite( pFileObject,
420 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
421 AFS_TRACE_LEVEL_WARNING,
422 "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
424 liStartingByte.QuadPart,
426 bRetry ? " RETRY" : "");
428 ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
430 if ( STATUS_PENDING == ntStatus)
433 bCompleteIrp = FALSE;
438 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
439 AFS_TRACE_LEVEL_ERROR,
440 "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
445 try_return( ntStatus);
450 // Save off the PID if this is not a paging IO
454 ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
455 ( ullProcessId != (ULONGLONG)AFSSysProcess &&
456 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
459 pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
461 if( ullProcessId == (ULONGLONG)AFSSysProcess)
463 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
464 AFS_TRACE_LEVEL_WARNING,
465 "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
474 // - if Paging then we need to do nothing (the precalls will
475 // have acquired the paging resource), for clarity we will collect
476 // the paging resource
477 // - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
478 // - Otherwise we collect the file shared, check against extending and
489 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
491 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
492 AFS_TRACE_LEVEL_VERBOSE,
493 "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
494 &pNPFcb->PagingResource,
495 PsGetCurrentThread());
497 AFSAcquireShared( &pNPFcb->PagingResource,
500 bReleasePaging = TRUE;
503 // We have the correct lock - we cannot have the wrong one
510 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
511 pFcb->Header.FileSize.QuadPart) ||
512 (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
513 liStartingByte.HighPart == -1)) ;
518 // Check for lock inversion
521 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
523 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
524 AFS_TRACE_LEVEL_VERBOSE,
525 "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
527 PsGetCurrentThread());
529 AFSAcquireExcl( &pNPFcb->Resource,
534 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
535 AFS_TRACE_LEVEL_VERBOSE,
536 "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
537 &pNPFcb->SectionObjectResource,
538 PsGetCurrentThread());
540 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
543 bReleaseSectionObject = TRUE;
545 if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
546 liStartingByte.HighPart == -1)
548 if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
550 liStartingByte = pFcb->Header.ValidDataLength;
554 liStartingByte = pFcb->Header.FileSize;
559 // We have the correct lock - even if we don't end up truncating
565 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
567 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
568 AFS_TRACE_LEVEL_VERBOSE,
569 "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
571 PsGetCurrentThread());
573 AFSAcquireShared( &pNPFcb->Resource,
578 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
579 AFS_TRACE_LEVEL_VERBOSE,
580 "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
581 &pNPFcb->SectionObjectResource,
582 PsGetCurrentThread());
584 AFSAcquireShared( &pNPFcb->SectionObjectResource,
587 bReleaseSectionObject = TRUE;
590 // Have things moved? Are we extending? If so, the the lock isn't OK
592 bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
596 AFSReleaseResource( &pNPFcb->Resource);
598 bReleaseMain = FALSE;
609 // Check the BR locks on the file.
612 if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
616 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
617 AFS_TRACE_LEVEL_ERROR,
618 "AFSCommonWrite (%p) Request failed due to lock conflict\n",
621 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
627 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
629 if( !NT_SUCCESS(ntStatus))
632 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
633 AFS_TRACE_LEVEL_ERROR,
634 "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
638 try_return( ntStatus );
644 // Fire off the request as appropriate
646 bCompleteIrp = FALSE;
653 // Main and SectionObject resources held Shared
656 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
657 AFS_TRACE_LEVEL_VERBOSE,
658 "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
660 liStartingByte.QuadPart,
662 bRetry ? " RETRY" : "");
664 ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, TRUE);
671 // if bPagingIo, Paging Resource held Shared
672 // else Main and SectionObject resources held Shared
675 if( bReleaseSectionObject)
678 AFSReleaseResource( &pNPFcb->SectionObjectResource);
680 bReleaseSectionObject = FALSE;
686 AFSReleaseResource( &pNPFcb->PagingResource);
688 bReleasePaging = FALSE;
694 AFSReleaseResource( &pNPFcb->Resource);
696 bReleaseMain = FALSE;
699 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
700 AFS_TRACE_LEVEL_VERBOSE,
701 "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
703 liStartingByte.QuadPart,
705 bRetry ? " RETRY" : "");
707 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
710 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp, liStartingByte, ulByteCount);
714 ntStatus = AFSNonCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount);
720 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
721 AFS_TRACE_LEVEL_VERBOSE,
722 "AFSCommonWrite (%p) Process complete Status %08lX\n",
726 ObDereferenceObject(pFileObject);
728 if( bReleaseSectionObject)
731 AFSReleaseResource( &pNPFcb->SectionObjectResource);
737 AFSReleaseResource( &pNPFcb->PagingResource);
743 AFSReleaseResource( &pNPFcb->Resource);
749 AFSCompleteRequest( Irp,
758 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
762 UNREFERENCED_PARAMETER(DeviceObject);
763 NTSTATUS ntStatus = STATUS_SUCCESS;
764 AFSPIOCtlIORequestCB stIORequestCB;
765 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
768 AFSPIOCtlIOResultCB stIOResultCB;
769 ULONG ulBytesReturned = 0;
770 AFSFileID stParentFID;
775 Irp->IoStatus.Information = 0;
777 RtlZeroMemory( &stIORequestCB,
778 sizeof( AFSPIOCtlIORequestCB));
780 if( pIrpSp->Parameters.Write.Length == 0)
784 // Nothing to do in this case
787 try_return( ntStatus);
790 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
792 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
794 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
795 AFS_TRACE_LEVEL_VERBOSE,
796 "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
797 &pFcb->NPFcb->Resource,
798 PsGetCurrentThread());
800 AFSAcquireShared( &pFcb->NPFcb->Resource,
804 // Get the parent fid to pass to the cm
807 RtlZeroMemory( &stParentFID,
810 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
814 // The parent directory FID of the node
817 stParentFID = pFcb->ObjectInformation->ParentFileId;
821 // Set the control block up
824 stIORequestCB.RequestId = pCcb->RequestID;
826 if( pFcb->ObjectInformation->VolumeCB != NULL)
828 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
832 // Lock down the buffer
835 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
836 pIrpSp->Parameters.Write.Length);
838 if( stIORequestCB.MappedBuffer == NULL)
841 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
844 stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
846 stIOResultCB.BytesProcessed = 0;
848 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
851 // Issue the request to the service
854 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
855 AFS_REQUEST_FLAG_SYNCHRONOUS,
861 (void *)&stIORequestCB,
862 sizeof( AFSPIOCtlIORequestCB),
866 if( !NT_SUCCESS( ntStatus))
869 try_return( ntStatus);
873 // Update the length written
876 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
880 if( stIORequestCB.MappedBuffer != NULL)
883 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
890 AFSReleaseResource( &pFcb->NPFcb->Resource);
898 // This function is called when we know we have to read from the AFS Cache.
900 // It ensures that we have exents for the entirety of the write and
901 // then pins the extents into memory (meaning that although we may
902 // add we will not remove). Then it creates a scatter gather write
903 // and fires off the IRPs
907 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
909 IN LARGE_INTEGER StartingByte,
912 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
913 VOID *pSystemBuffer = NULL;
914 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
915 BOOLEAN bLocked = FALSE;
916 BOOLEAN bCompleteIrp = TRUE;
917 AFSGatherIo *pGatherIo = NULL;
918 AFSIoRun *pIoRuns = NULL;
919 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
920 ULONG extentsCount = 0, runCount = 0;
921 AFSExtent *pStartExtent = NULL;
922 AFSExtent *pIgnoreExtent = NULL;
923 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
924 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
925 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
926 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
927 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
928 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
929 LARGE_INTEGER liCurrentTime, liLastRequestTime;
930 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
931 PFILE_OBJECT pCacheFileObject = NULL;
932 BOOLEAN bDerefExtents = FALSE;
937 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
938 AFS_TRACE_LEVEL_VERBOSE,
939 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
941 StartingByte.HighPart,
942 StartingByte.LowPart,
945 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
948 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
949 AFS_TRACE_LEVEL_ERROR,
950 "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
953 pIrpSp->Parameters.Write.Length,
954 pDevExt->Specific.RDR.MaxIo.QuadPart);
956 try_return( ntStatus = STATUS_UNSUCCESSFUL);
960 // Get the mapping for the buffer
962 pSystemBuffer = AFSLockSystemBuffer( Irp,
965 if( pSystemBuffer == NULL)
968 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
969 AFS_TRACE_LEVEL_ERROR,
970 "AFSNonCachedWrite (%p) Failed to map system buffer\n",
973 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
978 // Provoke a get of the extents - if we need to.
981 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
982 AFS_TRACE_LEVEL_VERBOSE,
983 "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
984 pFcb->ObjectInformation->FileId.Cell,
985 pFcb->ObjectInformation->FileId.Volume,
986 pFcb->ObjectInformation->FileId.Vnode,
987 pFcb->ObjectInformation->FileId.Unique,
988 StartingByte.QuadPart,
991 ntStatus = AFSRequestExtentsAsync( pFcb,
996 if (!NT_SUCCESS(ntStatus))
999 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1000 AFS_TRACE_LEVEL_ERROR,
1001 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1005 try_return( ntStatus);
1008 KeQueryTickCount( &liLastRequestTime);
1013 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1014 AFS_TRACE_LEVEL_VERBOSE,
1015 "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1016 &pFcb->NPFcb->Specific.File.ExtentsResource,
1017 PsGetCurrentThread());
1019 ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1021 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1024 pStartExtent = NULL;
1025 pIgnoreExtent = NULL;
1027 if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1032 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1034 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1035 AFS_TRACE_LEVEL_VERBOSE,
1036 "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1037 &pFcb->NPFcb->Specific.File.ExtentsResource,
1038 PsGetCurrentThread());
1040 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1044 // We will re-request the extents after waiting for them
1047 KeQueryTickCount( &liCurrentTime);
1049 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1052 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1053 AFS_TRACE_LEVEL_VERBOSE,
1054 "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1055 pFcb->ObjectInformation->FileId.Cell,
1056 pFcb->ObjectInformation->FileId.Volume,
1057 pFcb->ObjectInformation->FileId.Vnode,
1058 pFcb->ObjectInformation->FileId.Unique,
1059 StartingByte.QuadPart,
1062 ntStatus = AFSRequestExtentsAsync( pFcb,
1067 if (!NT_SUCCESS(ntStatus))
1070 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1071 AFS_TRACE_LEVEL_ERROR,
1072 "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1076 try_return( ntStatus);
1079 KeQueryTickCount( &liLastRequestTime);
1083 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1084 AFS_TRACE_LEVEL_VERBOSE,
1085 "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1086 pFcb->ObjectInformation->FileId.Cell,
1087 pFcb->ObjectInformation->FileId.Volume,
1088 pFcb->ObjectInformation->FileId.Vnode,
1089 pFcb->ObjectInformation->FileId.Unique,
1090 StartingByte.QuadPart,
1097 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
1099 if (!NT_SUCCESS(ntStatus))
1102 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1103 AFS_TRACE_LEVEL_ERROR,
1104 "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1105 pFcb->ObjectInformation->FileId.Cell,
1106 pFcb->ObjectInformation->FileId.Volume,
1107 pFcb->ObjectInformation->FileId.Vnode,
1108 pFcb->ObjectInformation->FileId.Unique,
1109 StartingByte.QuadPart,
1113 try_return( ntStatus);
1118 // As per the read path -
1121 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1122 AFS_TRACE_LEVEL_VERBOSE,
1123 "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1124 pFcb->ObjectInformation->FileId.Cell,
1125 pFcb->ObjectInformation->FileId.Volume,
1126 pFcb->ObjectInformation->FileId.Vnode,
1127 pFcb->ObjectInformation->FileId.Unique,
1128 StartingByte.QuadPart,
1131 ntStatus = AFSGetExtents( pFcb,
1138 if (!NT_SUCCESS(ntStatus))
1141 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1142 AFS_TRACE_LEVEL_ERROR,
1143 "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1147 try_return( ntStatus );
1150 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1151 AFS_TRACE_LEVEL_VERBOSE,
1152 "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1157 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1160 Irp->IoStatus.Information = ByteCount;
1164 // Setup the MD5 for each extent
1167 AFSSetupMD5Hash( pFcb,
1175 ntStatus = AFSProcessExtentRun( pSystemBuffer,
1181 if (!NT_SUCCESS(ntStatus))
1184 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1185 AFS_TRACE_LEVEL_ERROR,
1186 "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1191 try_return( ntStatus);
1195 // Retrieve the cache file object
1198 pCacheFileObject = AFSReferenceCacheFileObject();
1200 if( pCacheFileObject == NULL)
1203 ntStatus = STATUS_DEVICE_NOT_READY;
1205 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1206 AFS_TRACE_LEVEL_ERROR,
1207 "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1208 pFcb->ObjectInformation->FileId.Cell,
1209 pFcb->ObjectInformation->FileId.Volume,
1210 pFcb->ObjectInformation->FileId.Vnode,
1211 pFcb->ObjectInformation->FileId.Unique,
1212 StartingByte.QuadPart,
1216 try_return( ntStatus);
1219 if (runCount > AFS_MAX_STACK_IO_RUNS)
1222 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1223 runCount * sizeof( AFSIoRun ),
1225 if (NULL == pIoRuns)
1228 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1229 AFS_TRACE_LEVEL_ERROR,
1230 "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1233 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1242 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1244 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1253 if (!NT_SUCCESS(ntStatus))
1256 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1257 AFS_TRACE_LEVEL_ERROR,
1258 "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1262 try_return( ntStatus );
1265 AFSReferenceActiveExtents( pStartExtent,
1268 bDerefExtents = TRUE;
1270 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1271 AFS_TRACE_LEVEL_VERBOSE,
1272 "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1273 &pFcb->NPFcb->Specific.File.ExtentsResource,
1274 PsGetCurrentThread());
1276 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1279 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1280 sizeof( AFSGatherIo),
1283 if (NULL == pGatherIo)
1286 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1287 AFS_TRACE_LEVEL_ERROR,
1288 "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1291 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1292 AFS_TRACE_LEVEL_VERBOSE,
1293 "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1294 &pFcb->NPFcb->Specific.File.ExtentsResource,
1295 PsGetCurrentThread());
1297 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1301 AFSDereferenceActiveExtents( pStartExtent,
1304 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1307 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1310 // Initialize count to 1, that was we won't get an early
1311 // completion if the first irp completes before the second is
1314 pGatherIo->Count = 1;
1315 pGatherIo->Status = STATUS_SUCCESS;
1316 pGatherIo->MasterIrp = Irp;
1317 pGatherIo->Synchronous = TRUE;
1318 pGatherIo->CompleteMasterIrp = FALSE;
1320 bCompleteIrp = TRUE;
1322 if( pGatherIo->Synchronous)
1324 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1329 // Setup the MD5 for each extent
1332 AFSSetupMD5Hash( pFcb,
1341 // Pre-emptively set up the count
1344 Irp->IoStatus.Information = ByteCount;
1346 ntStatus = AFSQueueStartIos( pCacheFileObject,
1348 IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1353 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1354 AFS_TRACE_LEVEL_VERBOSE,
1355 "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1359 if( !NT_SUCCESS( ntStatus))
1362 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1363 AFS_TRACE_LEVEL_VERBOSE,
1364 "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1365 &pFcb->NPFcb->Specific.File.ExtentsResource,
1366 PsGetCurrentThread());
1368 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1372 AFSDereferenceActiveExtents( pStartExtent,
1375 try_return( ntStatus);
1379 // Wait for completion of All IOs we started.
1382 ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1388 if( NT_SUCCESS( ntStatus))
1391 ntStatus = pGatherIo->Status;
1394 if( !NT_SUCCESS( ntStatus))
1397 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1398 AFS_TRACE_LEVEL_VERBOSE,
1399 "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1400 &pFcb->NPFcb->Specific.File.ExtentsResource,
1401 PsGetCurrentThread());
1403 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1407 AFSDereferenceActiveExtents( pStartExtent,
1410 try_return( ntStatus);
1415 if( NT_SUCCESS( ntStatus) &&
1416 pStartExtent != NULL &&
1417 Irp->IoStatus.Information > 0)
1423 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1429 // Since this is dirty we can mark the extents dirty now.
1430 // AFSMarkDirty will dereference the extents. Do not call
1431 // AFSDereferenceActiveExtents() in this code path.
1443 // This was an uncached user write - tell the server to do
1444 // the flush when the worker thread next wakes up
1446 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1450 if( pCacheFileObject != NULL)
1452 AFSReleaseCacheFileObject( pCacheFileObject);
1455 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1456 AFS_TRACE_LEVEL_VERBOSE,
1457 "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1459 StartingByte.HighPart,
1460 StartingByte.LowPart,
1464 if (NT_SUCCESS(ntStatus) &&
1469 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1475 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1476 AFS_TRACE_LEVEL_VERBOSE,
1477 "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1478 &pFcb->NPFcb->Specific.File.ExtentsResource,
1479 PsGetCurrentThread());
1481 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1486 AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1489 if( NULL != pIoRuns &&
1490 stIoRuns != pIoRuns)
1492 AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1498 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1499 AFS_TRACE_LEVEL_VERBOSE,
1500 "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1503 Irp->IoStatus.Information);
1505 AFSCompleteRequest( Irp, ntStatus);
1514 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1516 IN LARGE_INTEGER StartingByte,
1519 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1520 VOID *pSystemBuffer = NULL;
1521 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1522 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1523 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1524 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1525 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
1526 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1527 BOOLEAN bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1528 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1529 AFSFileIOCB stFileIORequest;
1530 AFSFileIOResultCB stFileIOResult;
1531 ULONG ulResultLen = 0;
1536 Irp->IoStatus.Information = 0;
1538 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1539 AFS_TRACE_LEVEL_VERBOSE,
1540 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1542 StartingByte.HighPart,
1543 StartingByte.LowPart,
1546 if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1549 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1550 AFS_TRACE_LEVEL_ERROR,
1551 "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1554 pIrpSp->Parameters.Write.Length,
1555 pDevExt->Specific.RDR.MaxIo.QuadPart);
1557 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1561 // Get the mapping for the buffer
1563 pSystemBuffer = AFSLockSystemBuffer( Irp,
1566 if( pSystemBuffer == NULL)
1569 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1570 AFS_TRACE_LEVEL_ERROR,
1571 "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1574 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1578 // Issue the request at the service for processing
1581 ulResultLen = sizeof( AFSFileIOResultCB);
1583 RtlZeroMemory( &stFileIORequest,
1584 sizeof( AFSFileIOCB));
1586 RtlZeroMemory( &stFileIOResult,
1587 sizeof( AFSFileIOResultCB));
1589 stFileIORequest.SystemIOBuffer = pSystemBuffer;
1591 stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1593 stFileIORequest.IOLength = ByteCount;
1595 stFileIORequest.IOOffset = StartingByte;
1597 ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1599 if ( bNoIntermediateBuffering)
1602 ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1606 // Update file metadata
1609 stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1611 stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1613 stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1615 stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1617 stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1620 // Write the data to the service
1623 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1626 &pCcb->DirectoryCB->NameInformation.FileName,
1627 &pFcb->ObjectInformation->FileId,
1628 pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1629 pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1631 sizeof( AFSFileIOCB),
1635 if( NT_SUCCESS( ntStatus))
1638 Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1643 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1644 AFS_TRACE_LEVEL_ERROR,
1645 "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1653 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1654 AFS_TRACE_LEVEL_VERBOSE,
1655 "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1657 StartingByte.HighPart,
1658 StartingByte.LowPart,
1662 if (NT_SUCCESS(ntStatus) &&
1667 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1670 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1671 AFS_TRACE_LEVEL_VERBOSE,
1672 "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1675 Irp->IoStatus.Information);
1677 AFSCompleteRequest( Irp, ntStatus);
1685 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1687 IN LARGE_INTEGER StartingByte,
1689 IN BOOLEAN ForceFlush)
1691 UNREFERENCED_PARAMETER(DeviceObject);
1692 PVOID pSystemBuffer = NULL;
1693 NTSTATUS ntStatus = STATUS_SUCCESS;
1694 IO_STATUS_BLOCK iosbFlush;
1695 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1696 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
1697 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
1698 BOOLEAN bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1699 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
1700 PMDL pCurrentMdl = Irp->MdlAddress;
1701 LARGE_INTEGER liCurrentOffset;
1706 Irp->IoStatus.Information = 0;
1708 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1714 CcPrepareMdlWrite( pFileObject,
1720 ntStatus = Irp->IoStatus.Status;
1722 __except( EXCEPTION_EXECUTE_HANDLER)
1724 ntStatus = GetExceptionCode();
1726 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1727 AFS_TRACE_LEVEL_ERROR,
1728 "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1733 if( !NT_SUCCESS( ntStatus))
1737 // Free up any potentially allocated mdl's
1740 CcMdlWriteComplete( pFileObject,
1744 Irp->MdlAddress = NULL;
1746 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1747 AFS_TRACE_LEVEL_ERROR,
1748 "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1753 try_return( ntStatus);
1756 liCurrentOffset.QuadPart = StartingByte.QuadPart;
1758 while( ulTotalLen > 0)
1761 ntStatus = STATUS_SUCCESS;
1763 if( pCurrentMdl != NULL)
1766 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1767 NormalPagePriority);
1769 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1771 if( ulCurrentIO > ulTotalLen)
1773 ulCurrentIO = ulTotalLen;
1779 pSystemBuffer = AFSLockSystemBuffer( Irp,
1782 ulCurrentIO = ulTotalLen;
1785 if( pSystemBuffer == NULL)
1788 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1789 AFS_TRACE_LEVEL_ERROR,
1790 "AFSCachedWrite (%p) Failed to lock system buffer\n",
1793 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1799 if( !CcCopyWrite( pFileObject,
1806 // Failed to process request.
1809 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1810 AFS_TRACE_LEVEL_ERROR,
1811 "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1813 &pFileObject->FileName,
1814 liCurrentOffset.QuadPart,
1815 Irp->IoStatus.Status);
1817 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1820 __except( EXCEPTION_EXECUTE_HANDLER)
1823 ntStatus = GetExceptionCode();
1825 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1826 AFS_TRACE_LEVEL_ERROR,
1827 "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1829 &pFileObject->FileName,
1830 liCurrentOffset.QuadPart,
1834 if( !NT_SUCCESS( ntStatus))
1836 try_return( ntStatus);
1840 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1844 // We have detected a file we do a write through with.
1847 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1852 if( !NT_SUCCESS( iosbFlush.Status))
1855 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1856 AFS_TRACE_LEVEL_ERROR,
1857 "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1859 &pFileObject->FileName,
1860 pFcb->ObjectInformation->FileId.Cell,
1861 pFcb->ObjectInformation->FileId.Volume,
1862 pFcb->ObjectInformation->FileId.Vnode,
1863 pFcb->ObjectInformation->FileId.Unique,
1865 iosbFlush.Information);
1867 try_return( ntStatus = iosbFlush.Status);
1871 if( ulTotalLen <= ulCurrentIO)
1876 liCurrentOffset.QuadPart += ulCurrentIO;
1878 ulTotalLen -= ulCurrentIO;
1880 pCurrentMdl = pCurrentMdl->Next;
1885 if( NT_SUCCESS( ntStatus))
1888 Irp->IoStatus.Information = ByteCount;
1893 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1897 // If this extended the Vdl, then update it accordingly
1900 if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1903 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1907 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1910 // Write through asked for... Set things so that we get
1911 // flush when the worker thread next wakes up
1913 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1916 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1919 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1921 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1925 AFSCompleteRequest( Irp,
1934 AFSExtendingWrite( IN AFSFcb *Fcb,
1935 IN PFILE_OBJECT FileObject,
1936 IN LONGLONG NewLength)
1938 LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1939 LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1940 NTSTATUS ntStatus = STATUS_SUCCESS;
1941 AFSCcb *pCcb = (AFSCcb *)FileObject->FsContext2;
1943 if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1946 Fcb->Header.AllocationSize.QuadPart = NewLength;
1948 Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1951 if( NewLength > Fcb->Header.FileSize.QuadPart)
1954 Fcb->Header.FileSize.QuadPart = NewLength;
1956 Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1963 ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
1964 Fcb->ObjectInformation,
1967 if (NT_SUCCESS(ntStatus))
1970 KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1972 SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1975 // If the file is currently cached, then let the MM know about the extension
1978 if( CcIsFileCached( FileObject))
1980 CcSetFileSizes( FileObject,
1981 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1986 Fcb->Header.FileSize = liSaveFileSize;
1987 Fcb->Header.AllocationSize = liSaveAllocation;
1991 // DownConvert file resource to shared
1993 ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
1999 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2003 UNREFERENCED_PARAMETER(DeviceObject);
2004 NTSTATUS ntStatus = STATUS_SUCCESS;
2005 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2006 AFSFcb *pFcb = NULL;
2007 AFSCcb *pCcb = NULL;
2008 AFSPipeIORequestCB *pIoRequest = NULL;
2009 void *pBuffer = NULL;
2010 AFSPipeIOResultCB stIoResult;
2011 ULONG ulBytesReturned = 0;
2016 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2018 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2020 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2021 AFS_TRACE_LEVEL_VERBOSE,
2022 "AFSShareWrite On pipe %wZ Length %08lX\n",
2023 &pCcb->DirectoryCB->NameInformation.FileName,
2024 pIrpSp->Parameters.Write.Length);
2026 if( pIrpSp->Parameters.Write.Length == 0)
2030 // Nothing to do in this case
2033 try_return( ntStatus);
2037 // Retrieve the buffer for the read request
2040 pBuffer = AFSLockSystemBuffer( Irp,
2041 pIrpSp->Parameters.Write.Length);
2043 if( pBuffer == NULL)
2046 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2047 AFS_TRACE_LEVEL_ERROR,
2048 "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2049 &pCcb->DirectoryCB->NameInformation.FileName);
2051 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2054 AFSAcquireShared( &pFcb->NPFcb->Resource,
2057 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2058 sizeof( AFSPipeIORequestCB) +
2059 pIrpSp->Parameters.Write.Length,
2060 AFS_GENERIC_MEMORY_14_TAG);
2062 if( pIoRequest == NULL)
2065 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2068 RtlZeroMemory( pIoRequest,
2069 sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2071 pIoRequest->RequestId = pCcb->RequestID;
2073 pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2075 pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2077 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2079 pIrpSp->Parameters.Write.Length);
2081 stIoResult.BytesProcessed = 0;
2083 ulBytesReturned = sizeof( AFSPipeIOResultCB);
2086 // Issue the open request to the service
2089 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2090 AFS_REQUEST_FLAG_SYNCHRONOUS,
2092 &pCcb->DirectoryCB->NameInformation.FileName,
2097 sizeof( AFSPipeIORequestCB) +
2098 pIrpSp->Parameters.Write.Length,
2102 if( !NT_SUCCESS( ntStatus))
2105 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2106 AFS_TRACE_LEVEL_ERROR,
2107 "AFSShareWrite (%p) Failed service write Status %08lX\n",
2111 try_return( ntStatus);
2114 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
2115 AFS_TRACE_LEVEL_VERBOSE,
2116 "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2117 &pCcb->DirectoryCB->NameInformation.FileName,
2118 stIoResult.BytesProcessed);
2120 Irp->IoStatus.Information = stIoResult.BytesProcessed;
2127 AFSReleaseResource( &pFcb->NPFcb->Resource);
2130 if( pIoRequest != NULL)
2133 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);