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 AFSCachedRead( IN PDEVICE_OBJECT DeviceObject,
45 IN LARGE_INTEGER StartingByte,
48 NTSTATUS ntStatus = STATUS_SUCCESS;
49 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
50 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
51 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
52 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
53 BOOLEAN bSynchronousIo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
54 VOID *pSystemBuffer = NULL;
55 ULONG ulCurrentIO = 0, ulTotalLen = ByteCount;
56 PMDL pCurrentMdl = Irp->MdlAddress;
57 LARGE_INTEGER liCurrentOffset;
62 Irp->IoStatus.Information = 0;
64 liCurrentOffset.QuadPart = StartingByte.QuadPart;
66 while( ulTotalLen > 0)
69 ntStatus = STATUS_SUCCESS;
71 if( pCurrentMdl != NULL)
74 ASSERT( pCurrentMdl != NULL);
76 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
79 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
81 if( ulCurrentIO > ulTotalLen)
83 ulCurrentIO = ulTotalLen;
89 pSystemBuffer = AFSLockSystemBuffer( Irp,
92 ulCurrentIO = ulTotalLen;
95 if( pSystemBuffer == NULL)
98 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
99 AFS_TRACE_LEVEL_ERROR,
100 "AFSCachedRead (%08lX) Failed to lock system buffer\n",
103 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
109 if( !CcCopyRead( pFileObject,
118 // Failed to process request.
121 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
122 AFS_TRACE_LEVEL_ERROR,
123 "AFSCachedRead (%08lX) Failed CcCopyRead() %wZ @ %0I64X Status %08lX\n",
125 &pFileObject->FileName,
126 liCurrentOffset.QuadPart,
127 Irp->IoStatus.Status);
129 try_return( ntStatus = Irp->IoStatus.Status);
132 __except( EXCEPTION_EXECUTE_HANDLER)
134 ntStatus = GetExceptionCode();
136 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
137 AFS_TRACE_LEVEL_ERROR,
138 "AFSCachedRead (%08lX) CcCopyRead() Threw exception %wZ @ %0I64X Status %08lX\n",
140 &pFileObject->FileName,
141 liCurrentOffset.QuadPart,
145 if( !NT_SUCCESS( ntStatus))
148 try_return( ntStatus);
151 if( ulTotalLen <= ulCurrentIO)
156 liCurrentOffset.QuadPart += ulCurrentIO;
158 ulTotalLen -= ulCurrentIO;
160 pCurrentMdl = pCurrentMdl->Next;
165 if( NT_SUCCESS( ntStatus))
168 Irp->IoStatus.Information = ByteCount;
171 // Update the CBO if this is a sync read
177 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
181 AFSCompleteRequest( Irp,
190 AFSNonCachedRead( IN PDEVICE_OBJECT DeviceObject,
192 IN LARGE_INTEGER StartingByte)
194 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
195 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
196 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
197 AFSFcb *pFcb = (AFSFcb *)pFileObject->FsContext;
198 AFSCcb *pCcb = (AFSCcb *)pFileObject->FsContext2;
199 BOOLEAN bSynchronousIo = IoIsOperationSynchronous(Irp);
200 VOID *pSystemBuffer = NULL;
201 BOOLEAN bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
202 BOOLEAN bLocked = FALSE;
203 AFSGatherIo *pGatherIo = NULL;
204 AFSIoRun *pIoRuns = NULL;
205 AFSIoRun stIoRuns[AFS_MAX_STACK_IO_RUNS];
206 ULONG extentsCount = 0, runCount = 0;
207 AFSExtent *pStartExtent = NULL;
208 AFSExtent *pIgnoreExtent = NULL;
209 BOOLEAN bExtentsMapped = FALSE;
210 BOOLEAN bCompleteIrp = TRUE;
211 ULONG ulReadByteCount;
213 AFSDeviceExt *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
214 ULONG ulRequestCount = 0;
215 LARGE_INTEGER liCurrentTime, liLastRequestTime;
216 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
217 PFILE_OBJECT pCacheFileObject = NULL;
222 ulByteCount = pIrpSp->Parameters.Read.Length;
224 if (ulByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
227 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
228 AFS_TRACE_LEVEL_ERROR,
229 "AFSNonCachedRead (%08lX) Request larger than MaxIO %I64X\n",
231 pDevExt->Specific.RDR.MaxIo.QuadPart);
233 try_return( ntStatus = STATUS_UNSUCCESSFUL);
236 pSystemBuffer = AFSLockSystemBuffer( Irp,
239 if( pSystemBuffer == NULL)
242 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
243 AFS_TRACE_LEVEL_ERROR,
244 "AFSNonCachedRead (%08lX) Failed to map system buffer\n",
247 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
250 if( StartingByte.QuadPart + ulByteCount > pFcb->Header.FileSize.QuadPart)
252 ULONG zeroCount = (ULONG) (StartingByte.QuadPart + ulByteCount - pFcb->Header.FileSize.QuadPart);
253 ulReadByteCount = (ULONG)(pFcb->Header.FileSize.QuadPart - StartingByte.QuadPart);
259 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
260 AFS_TRACE_LEVEL_VERBOSE,
261 "AFSNonCachedRead (%08lX) Zeroing to EOF zero byte length %08lX\n",
265 RtlZeroMemory( ((PCHAR)pSystemBuffer) + ulReadByteCount, zeroCount);
269 ulReadByteCount = ulByteCount;
273 // Provoke a get of the extents - if we need to.
278 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
279 AFS_TRACE_LEVEL_VERBOSE,
280 "AFSNonCachedRead Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
281 pFcb->ObjectInformation->FileId.Cell,
282 pFcb->ObjectInformation->FileId.Volume,
283 pFcb->ObjectInformation->FileId.Vnode,
284 pFcb->ObjectInformation->FileId.Unique,
285 StartingByte.QuadPart,
288 ntStatus = AFSRequestExtentsAsync( pFcb,
293 if (!NT_SUCCESS(ntStatus))
296 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
297 AFS_TRACE_LEVEL_ERROR,
298 "AFSNonCachedRead (%08lX) Failed to request extents Status %08lX\n",
302 try_return( ntStatus);
305 KeQueryTickCount( &liLastRequestTime);
310 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
311 AFS_TRACE_LEVEL_VERBOSE,
312 "AFSNonCachedRead Acquiring Fcb extents lock %08lX SHARED %08lX\n",
313 &pFcb->NPFcb->Specific.File.ExtentsResource,
314 PsGetCurrentThread());
316 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
320 pIgnoreExtent = NULL;
322 if( AFSDoExtentsMapRegion( pFcb,
331 KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete);
333 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
334 AFS_TRACE_LEVEL_VERBOSE,
335 "AFSNonCachedRead Releasing Fcb extents lock %08lX SHARED %08lX\n",
336 &pFcb->NPFcb->Specific.File.ExtentsResource,
337 PsGetCurrentThread());
339 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
343 // We will re-request the extents after 10 seconds of waiting for them
346 KeQueryTickCount( &liCurrentTime);
348 if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
351 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
352 AFS_TRACE_LEVEL_VERBOSE,
353 "AFSNonCachedRead Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
354 pFcb->ObjectInformation->FileId.Cell,
355 pFcb->ObjectInformation->FileId.Volume,
356 pFcb->ObjectInformation->FileId.Vnode,
357 pFcb->ObjectInformation->FileId.Unique,
358 StartingByte.QuadPart,
361 ntStatus = AFSRequestExtentsAsync( pFcb,
366 if (!NT_SUCCESS(ntStatus))
369 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
370 AFS_TRACE_LEVEL_ERROR,
371 "AFSNonCachedRead (%08lX) Failed to request extents Status %08lX\n",
375 try_return( ntStatus);
378 KeQueryTickCount( &liLastRequestTime);
381 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
382 AFS_TRACE_LEVEL_VERBOSE,
383 "AFSNonCachedRead Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
384 pFcb->ObjectInformation->FileId.Cell,
385 pFcb->ObjectInformation->FileId.Volume,
386 pFcb->ObjectInformation->FileId.Vnode,
387 pFcb->ObjectInformation->FileId.Unique,
388 StartingByte.QuadPart,
391 ntStatus = AFSWaitForExtentMapping ( pFcb, pCcb);
393 if (!NT_SUCCESS(ntStatus))
396 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
397 AFS_TRACE_LEVEL_ERROR,
398 "AFSNonCachedRead Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
399 pFcb->ObjectInformation->FileId.Cell,
400 pFcb->ObjectInformation->FileId.Volume,
401 pFcb->ObjectInformation->FileId.Vnode,
402 pFcb->ObjectInformation->FileId.Unique,
403 StartingByte.QuadPart,
407 try_return( ntStatus);
412 // At this stage we know that the extents are fully mapped and
413 // that, because we took a reference they won't be unmapped.
414 // Thus the list will not move between the start and end.
417 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
418 AFS_TRACE_LEVEL_VERBOSE,
419 "AFSNonCachedRead Extents mapped for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
420 pFcb->ObjectInformation->FileId.Cell,
421 pFcb->ObjectInformation->FileId.Volume,
422 pFcb->ObjectInformation->FileId.Vnode,
423 pFcb->ObjectInformation->FileId.Unique,
424 StartingByte.QuadPart,
427 ntStatus = AFSGetExtents( pFcb,
434 if (!NT_SUCCESS(ntStatus))
437 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
438 AFS_TRACE_LEVEL_ERROR,
439 "AFSNonCachedRead (%08lX) Failed to retrieve mapped extents Status %08lX\n",
443 try_return( ntStatus );
446 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
447 AFS_TRACE_LEVEL_VERBOSE,
448 "AFSNonCachedRead (%08lX) Successfully retrieved map extents count %08lX run count %08lX\n",
453 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
456 Irp->IoStatus.Information = ulReadByteCount;
458 ntStatus = AFSProcessExtentRun( pSystemBuffer,
464 if (!NT_SUCCESS(ntStatus))
467 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
468 AFS_TRACE_LEVEL_ERROR,
469 "AFSNonCachedRead (%08lX) Failed to process extent run for non-persistent cache Status %08lX\n",
474 try_return( ntStatus);
478 // Retrieve the cache file object
481 pCacheFileObject = AFSReferenceCacheFileObject();
483 if( pCacheFileObject == NULL)
486 ntStatus = STATUS_DEVICE_NOT_READY;
488 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
489 AFS_TRACE_LEVEL_ERROR,
490 "AFSNonCachedRead Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
491 pFcb->ObjectInformation->FileId.Cell,
492 pFcb->ObjectInformation->FileId.Volume,
493 pFcb->ObjectInformation->FileId.Vnode,
494 pFcb->ObjectInformation->FileId.Unique,
495 StartingByte.QuadPart,
499 try_return( ntStatus);
502 if (runCount > AFS_MAX_STACK_IO_RUNS)
505 pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
506 runCount * sizeof( AFSIoRun ),
511 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
512 AFS_TRACE_LEVEL_ERROR,
513 "AFSNonCachedRead (%08lX) Failed to allocate IO run block\n",
516 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
525 RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
527 ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
536 if (!NT_SUCCESS(ntStatus))
539 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
540 AFS_TRACE_LEVEL_ERROR,
541 "AFSNonCachedRead (%08lX) Failed to initialize IO run block Status %08lX\n",
545 try_return( ntStatus );
548 AFSReferenceActiveExtents( pStartExtent,
551 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
552 AFS_TRACE_LEVEL_VERBOSE,
553 "AFSNonCachedRead Releasing Fcb extents lock %08lX SHARED %08lX\n",
554 &pFcb->NPFcb->Specific.File.ExtentsResource,
555 PsGetCurrentThread());
557 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
560 pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
561 sizeof( AFSGatherIo ),
564 if (NULL == pGatherIo)
567 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
568 AFS_TRACE_LEVEL_ERROR,
569 "AFSNonCachedRead (%08lX) Failed to allocate IO gather block\n",
572 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
573 AFS_TRACE_LEVEL_VERBOSE,
574 "AFSNonCachedRead Acquiring(2) Fcb extents lock %08lX SHARED %08lX\n",
575 &pFcb->NPFcb->Specific.File.ExtentsResource,
576 PsGetCurrentThread());
578 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
582 AFSDereferenceActiveExtents( pStartExtent,
585 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
588 RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
591 // Initialize count to 1, that was we won't get an early
592 // completion if the first irp completes before the second is
595 pGatherIo->Count = 1;
596 pGatherIo->Status = STATUS_SUCCESS;
597 pGatherIo->MasterIrp = Irp;
598 pGatherIo->Synchronous = TRUE;
599 pGatherIo->Fcb = pFcb;
600 pGatherIo->CompleteMasterIrp = FALSE;
604 if (pGatherIo->Synchronous)
606 KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
610 IoMarkIrpPending( Irp);
614 // Pre-emptively set up the count
617 Irp->IoStatus.Information = ulByteCount;
619 ntStatus = AFSQueueStartIos( pCacheFileObject,
621 IRP_READ_OPERATION | IRP_SYNCHRONOUS_API,
626 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
627 AFS_TRACE_LEVEL_VERBOSE,
628 "AFSNonCachedRead (%08lX) AFSStartIos completed Status %08lX\n",
632 if( !NT_SUCCESS( ntStatus))
635 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
636 AFS_TRACE_LEVEL_VERBOSE,
637 "AFSNonCachedRead Acquiring(3) Fcb extents lock %08lX SHARED %08lX\n",
638 &pFcb->NPFcb->Specific.File.ExtentsResource,
639 PsGetCurrentThread());
641 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
645 AFSDereferenceActiveExtents( pStartExtent,
648 try_return( ntStatus);
652 // Wait for completion of all IOs we started.
654 (VOID) KeWaitForSingleObject( &pGatherIo->Event,
660 ntStatus = pGatherIo->Status;
664 // Setup the MD5 for each extent
667 AFSSetupMD5Hash( pFcb,
674 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
675 AFS_TRACE_LEVEL_VERBOSE,
676 "AFSNonCachedRead (%08lX) AFSStartIos wait completed Status %08lX\n",
680 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
681 AFS_TRACE_LEVEL_VERBOSE,
682 "AFSNonCachedRead Acquiring(4) Fcb extents lock %08lX SHARED %08lX\n",
683 &pFcb->NPFcb->Specific.File.ExtentsResource,
684 PsGetCurrentThread());
686 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
690 AFSDereferenceActiveExtents( pStartExtent,
693 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
694 AFS_TRACE_LEVEL_VERBOSE,
695 "AFSNonCachedRead Releasing Fcb extents lock %08lX SHARED %08lX\n",
696 &pFcb->NPFcb->Specific.File.ExtentsResource,
697 PsGetCurrentThread());
699 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
703 // The data is there now. Give back the extents now so the service
706 (VOID) AFSReleaseExtentsWithFlush( pFcb,
711 if( pCacheFileObject != NULL)
713 AFSReleaseCacheFileObject( pCacheFileObject);
716 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
717 AFS_TRACE_LEVEL_VERBOSE,
718 "AFSNonCachedRead (%08lX) Completed request Status %08lX\n",
722 if (NT_SUCCESS(ntStatus) &&
724 BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO))
727 // Update the CBO if this is a sync, nopaging read
729 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ulByteCount;
735 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
736 AFS_TRACE_LEVEL_VERBOSE,
737 "AFSNonCachedRead Releasing Fcb extents lock %08lX SHARED %08lX\n",
738 &pFcb->NPFcb->Specific.File.ExtentsResource,
739 PsGetCurrentThread());
741 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
746 AFSExFreePool(pGatherIo);
749 if (NULL != pIoRuns && stIoRuns != pIoRuns)
751 AFSExFreePool(pIoRuns);
757 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
758 AFS_TRACE_LEVEL_VERBOSE,
759 "AFSNonCachedRead Completing irp %08lX Status %08lX Info %08lX\n",
762 Irp->IoStatus.Information);
764 AFSCompleteRequest( Irp, ntStatus );
770 // Function: AFSDispatch
774 // A shim around AFSCommonRead (qv)
777 AFSRead( IN PDEVICE_OBJECT LibDeviceObject,
781 NTSTATUS ntStatus = STATUS_SUCCESS;
786 ntStatus = AFSCommonRead( AFSRDRDeviceObject, Irp, NULL);
788 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
791 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
793 AFSDumpTraceFilesFnc();
803 // This function is a slightly widened Dispatch handler for the
804 // AFS Read function. The thrid parameter is FALSE if we were called
805 // at our dispatch point and TRUE if we have been posted.
807 // After doing the obvious (completing MDL writes and so forth)
808 // we then post, or not.
812 // A status is returned for the function
816 AFSCommonRead( IN PDEVICE_OBJECT DeviceObject,
818 IN HANDLE OnBehalfOf)
821 NTSTATUS ntStatus = STATUS_SUCCESS;
822 AFSDeviceExt *pDeviceExt;
823 IO_STACK_LOCATION *pIrpSp;
826 BOOLEAN bReleaseMain = FALSE;
827 BOOLEAN bReleasePaging = FALSE;
828 BOOLEAN bPagingIo = FALSE;
829 BOOLEAN bNonCachedIo = FALSE;
830 BOOLEAN bCompleteIrp = TRUE;
832 PFILE_OBJECT pFileObject = NULL;
833 LARGE_INTEGER liStartingByte;
835 VOID *pSystemBuffer = NULL;
836 HANDLE hCallingUser = NULL;
838 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
839 pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
844 // Decode the fileobject
846 pFileObject = pIrpSp->FileObject;
849 // There is a risk (albeit infinitely small) that the Irp will
850 // complete before this function exits, then a cleanup and
851 // close will happen and the FCB will be torn down before we
852 // get to the try_exit. Pin the file Object which will pin the FCB
855 ObReferenceObject( pFileObject);
858 // If we are in shutdown mode then fail the request
861 if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
864 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
865 AFS_TRACE_LEVEL_WARNING,
866 "AFSCommonRead (%08lX) Open request after shutdown\n",
869 try_return( ntStatus = STATUS_TOO_LATE);
872 pFcb = (AFSFcb *)pFileObject->FsContext;
874 pCcb = (AFSCcb *)pFileObject->FsContext2;
879 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
880 AFS_TRACE_LEVEL_ERROR,
881 "AFSCommonRead Attempted read (%08lX) when pFcb == NULL\n",
884 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
887 bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
888 bNonCachedIo = BooleanFlagOn( Irp->Flags,IRP_NOCACHE);
890 liStartingByte = pIrpSp->Parameters.Read.ByteOffset;
891 ulByteCount = pIrpSp->Parameters.Read.Length;
893 if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
894 pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
895 pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
898 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
899 AFS_TRACE_LEVEL_ERROR,
900 "AFSCommonRead Attempted read (%08lX) on an invalid node type %08lX\n",
902 pFcb->Header.NodeTypeCode);
904 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
908 // If this is a read against an IOCtl node then handle it
909 // in a different pathway
912 if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
915 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
916 AFS_TRACE_LEVEL_VERBOSE,
917 "AFSCommonRead (%08lX) Processing file (PIOCTL) Offset %I64X Length %08lX Irp Flags %08lX\n",
919 liStartingByte.QuadPart,
923 ntStatus = AFSIOCtlRead( DeviceObject,
926 try_return( ntStatus);
928 else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
931 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
932 AFS_TRACE_LEVEL_VERBOSE,
933 "AFSCommonRead (%08lX) Processing file (SHARE) Offset %I64X Length %08lX Irp Flags %08lX\n",
935 liStartingByte.QuadPart,
939 ntStatus = AFSShareRead( DeviceObject,
942 try_return( ntStatus);
946 // No fileobject yet? Bail.
948 if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
949 NULL == pDeviceExt->Specific.RDR.CacheFileObject)
952 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
953 AFS_TRACE_LEVEL_ERROR,
954 "AFSCommonRead (%08lX) Request failed due to AFS cache closed\n",
957 try_return( ntStatus = STATUS_TOO_LATE );
960 if( pIrpSp->Parameters.Read.Length == 0)
963 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
964 AFS_TRACE_LEVEL_VERBOSE,
965 "AFSCommonRead (%08lX) Request completed due to zero length\n",
968 try_return( ntStatus);
971 if ( FlagOn(pIrpSp->MinorFunction, IRP_MN_COMPLETE) )
974 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
975 AFS_TRACE_LEVEL_VERBOSE,
976 "AFSCommonRead (%08lX) IRP_MN_COMPLETE being processed\n",
979 CcMdlReadComplete(pIrpSp->FileObject, Irp->MdlAddress);
982 // Mdl is now Deallocated
985 Irp->MdlAddress = NULL;
987 try_return( ntStatus = STATUS_SUCCESS );
991 // If we get a non cached IO for a cached file we should do a purge.
992 // For now we will just promote to cached
994 if (NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo)
997 bNonCachedIo = FALSE;
1001 // Setup the calling process
1004 if( NULL == OnBehalfOf)
1007 hCallingUser = PsGetCurrentProcessId();
1012 hCallingUser = OnBehalfOf;
1016 // We acquire the main/paging resource first to synchronize
1017 // against size checks.
1023 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1024 AFS_TRACE_LEVEL_VERBOSE,
1025 "AFSCommonRead Acquiring Fcb PagingIo lock %08lX SHARED %08lX\n",
1026 &pFcb->NPFcb->PagingResource,
1027 PsGetCurrentThread());
1029 AFSAcquireShared( &pFcb->NPFcb->PagingResource,
1032 bReleasePaging = TRUE;
1037 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1038 AFS_TRACE_LEVEL_VERBOSE,
1039 "AFSCommonRead Acquiring Fcb lock %08lX SHARED %08lX\n",
1040 &pFcb->NPFcb->Resource,
1041 PsGetCurrentThread());
1043 AFSAcquireShared( &pFcb->NPFcb->Resource,
1046 bReleaseMain = TRUE;
1049 // Check the BR locks
1052 if( !FsRtlCheckLockForReadAccess( &pFcb->Specific.File.FileLock,
1056 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1057 AFS_TRACE_LEVEL_ERROR,
1058 "AFSCommonRead (%08lX) Request failed due to lock conflict\n",
1061 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
1065 if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
1066 BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1069 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1070 AFS_TRACE_LEVEL_ERROR,
1071 "AFSCommonRead (%08lX) Request failed due to file deleted\n",
1074 try_return( ntStatus = STATUS_FILE_DELETED);
1078 // If the read starts beyond End of File, return EOF.
1081 if( liStartingByte.QuadPart >= pFcb->Header.FileSize.QuadPart)
1084 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1085 AFS_TRACE_LEVEL_VERBOSE,
1086 "AFSCommonRead (%08lX) Request beyond EOF %I64X\n",
1088 pFcb->Header.FileSize.QuadPart);
1090 try_return( ntStatus = STATUS_END_OF_FILE);
1096 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.FileSize.QuadPart)
1099 ulByteCount = (ULONG)(pFcb->Header.FileSize.QuadPart - liStartingByte.QuadPart);
1101 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1102 AFS_TRACE_LEVEL_VERBOSE,
1103 "AFSCommonRead (%08lX) Truncated read request to %08lX\n",
1109 // Is this Fcb valid???
1112 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
1115 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1116 AFS_TRACE_LEVEL_ERROR,
1117 "AFSCommonRead (%08lX) Failing request due to INVALID fcb\n",
1120 Irp->IoStatus.Information = 0;
1122 try_return( ntStatus = STATUS_FILE_DELETED);
1126 // Save off the PID if this is not a paging IO
1130 ( pFcb->Specific.File.ExtentProcessId == 0 ||
1131 ( PsGetCurrentProcessId() != AFSSysProcess &&
1132 pFcb->Specific.File.ExtentProcessId != (ULONGLONG)PsGetCurrentProcessId())))
1135 pFcb->Specific.File.ExtentProcessId = (ULONGLONG)PsGetCurrentProcessId();
1137 if( pFcb->Specific.File.ExtentProcessId == (ULONGLONG)AFSSysProcess)
1139 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1140 AFS_TRACE_LEVEL_WARNING,
1141 "%s Setting ExtentProcessId to system process for Fcb %p\n",
1146 pFcb->Specific.File.ExtentThreadId = (ULONGLONG)PsGetCurrentThreadId();
1151 // If this is going to be posted OR this is a cached read,
1152 // then ask for the extents before we post.
1155 if( !bPagingIo && !bNonCachedIo)
1158 ntStatus = AFSRequestExtentsAsync( pFcb, pCcb, &liStartingByte, ulByteCount);
1160 if (!NT_SUCCESS(ntStatus))
1163 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1164 AFS_TRACE_LEVEL_ERROR,
1165 "AFSCommonRead (%08lX) Failed to request extents Status %08lX\n",
1169 try_return( ntStatus );
1175 // If this is an cached IO
1177 if( (!bPagingIo && !bNonCachedIo))
1180 // This is a top level irp. Init the caching if it has not yet
1181 // been initialzed for this FO
1184 if( pFileObject->PrivateCacheMap == NULL)
1190 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1191 AFS_TRACE_LEVEL_VERBOSE,
1192 "AFSCommonRead Initialize caching on Fcb %08lX FO %08lX\n",
1196 CcInitializeCacheMap( pFileObject,
1197 (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
1199 AFSLibCacheManagerCallbacks,
1202 CcSetReadAheadGranularity( pFileObject,
1203 pDeviceExt->Specific.RDR.MaximumRPCLength);
1205 CcSetDirtyPageThreshold( pFileObject,
1206 AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength);
1208 __except( EXCEPTION_EXECUTE_HANDLER)
1211 ntStatus = GetExceptionCode();
1213 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1214 AFS_TRACE_LEVEL_ERROR,
1215 "AFSCommonRead (%08lX) Exception thrown while initializing cache map Status %08lX\n",
1220 if( !NT_SUCCESS( ntStatus))
1223 try_return( ntStatus);
1228 // And if this is MDL operation, deal with it now (yes we
1229 // could post, but we are almost certainly posted
1230 // already and we don't want to grow and SVA for it..)
1233 if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1238 CcMdlRead( pFileObject,
1243 ntStatus = Irp->IoStatus.Status;
1245 __except( EXCEPTION_EXECUTE_HANDLER)
1247 ntStatus = GetExceptionCode();
1249 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1250 AFS_TRACE_LEVEL_ERROR,
1251 "AFSCommonRead (%08lX) Exception thrown during mdl read Status %08lX\n",
1256 if( !NT_SUCCESS( ntStatus))
1259 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1260 AFS_TRACE_LEVEL_ERROR,
1261 "AFSCommonRead (%08lX) Failed to process MDL read Status %08lX\n",
1265 try_return( ntStatus);
1269 // Update the CBO if this is a sync read
1272 if( BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO))
1275 pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
1278 try_return( ntStatus);
1283 // The called request completes the IRP for us.
1286 bCompleteIrp = FALSE;
1292 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1293 AFS_TRACE_LEVEL_VERBOSE,
1294 "AFSCommonRead (%08lX) Processing CACHED request Offset %I64X Len %08lX\n",
1296 liStartingByte.QuadPart,
1299 ntStatus = AFSCachedRead( DeviceObject, Irp, liStartingByte, ulByteCount);
1304 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1305 AFS_TRACE_LEVEL_VERBOSE,
1306 "AFSCommonRead (%08lX) Processing NON-CACHED request Offset %I64X Len %08lX\n",
1308 liStartingByte.QuadPart,
1311 ntStatus = AFSNonCachedRead( DeviceObject, Irp, liStartingByte);
1315 // We won't do this for now in read processing ...
1322 if( pFcb->Specific.File.ExtentsDirtyCount > 0 ||
1323 pFcb->Specific.File.ExtentLength > 1500)
1326 AFSQueueFlushExtents( pFcb,
1333 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1334 AFS_TRACE_LEVEL_VERBOSE,
1335 "AFSCommonRead (%08lX) Process complete Status %08lX\n",
1342 AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1348 AFSReleaseResource( &pFcb->NPFcb->Resource);
1354 AFSCompleteRequest( Irp, ntStatus);
1357 ObDereferenceObject( pFileObject);
1364 AFSIOCtlRead( IN PDEVICE_OBJECT DeviceObject,
1368 NTSTATUS ntStatus = STATUS_SUCCESS;
1369 AFSPIOCtlIORequestCB stIORequestCB;
1370 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1371 AFSFcb *pFcb = NULL;
1372 AFSCcb *pCcb = NULL;
1373 AFSPIOCtlIOResultCB stIOResultCB;
1374 ULONG ulBytesReturned = 0;
1375 AFSFileID stParentFID;
1380 RtlZeroMemory( &stIORequestCB,
1381 sizeof( AFSPIOCtlIORequestCB));
1383 if( pIrpSp->Parameters.Read.Length == 0)
1387 // Nothing to do in this case
1390 try_return( ntStatus);
1393 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1395 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1397 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1398 AFS_TRACE_LEVEL_VERBOSE,
1399 "AFSIOCtlRead Acquiring Fcb lock %08lX SHARED %08lX\n",
1400 &pFcb->NPFcb->Resource,
1401 PsGetCurrentThread());
1403 AFSAcquireShared( &pFcb->NPFcb->Resource,
1407 // Get the parent fid to pass to the cm
1410 RtlZeroMemory( &stParentFID,
1411 sizeof( AFSFileID));
1413 if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
1417 // The parent directory FID of the node
1420 ASSERT( pFcb->ObjectInformation->ParentObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY);
1422 stParentFID = pFcb->ObjectInformation->ParentObjectInformation->FileId;
1426 // Set the control block up
1429 stIORequestCB.RequestId = pCcb->RequestID;
1431 if( pFcb->ObjectInformation->VolumeCB != NULL)
1433 stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1437 // Lock down the buffer
1440 stIORequestCB.MappedBuffer = AFSMapToService( Irp,
1441 pIrpSp->Parameters.Read.Length);
1443 if( stIORequestCB.MappedBuffer == NULL)
1446 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1449 stIORequestCB.BufferLength = pIrpSp->Parameters.Read.Length;
1451 stIOResultCB.BytesProcessed = 0;
1453 ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
1456 // Issue the request to the service
1459 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_READ,
1460 AFS_REQUEST_FLAG_SYNCHRONOUS,
1464 (void *)&stIORequestCB,
1465 sizeof( AFSPIOCtlIORequestCB),
1469 if( !NT_SUCCESS( ntStatus))
1472 try_return( ntStatus);
1476 // Update the length read
1479 Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1483 if( stIORequestCB.MappedBuffer != NULL)
1486 AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1493 AFSReleaseResource( &pFcb->NPFcb->Resource);
1501 AFSShareRead( IN PDEVICE_OBJECT DeviceObject,
1505 NTSTATUS ntStatus = STATUS_SUCCESS;
1506 AFSPIOCtlIORequestCB stIORequestCB;
1507 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1508 AFSFcb *pFcb = NULL;
1509 AFSCcb *pCcb = NULL;
1510 ULONG ulBytesReturned = 0;
1511 void *pBuffer = NULL;
1512 AFSPipeIORequestCB stIoRequest;
1517 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1519 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1521 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1522 AFS_TRACE_LEVEL_VERBOSE,
1523 "AFSShareRead On pipe %wZ Length %08lX\n",
1524 &pCcb->DirectoryCB->NameInformation.FileName,
1525 pIrpSp->Parameters.Read.Length);
1527 if( pIrpSp->Parameters.Read.Length == 0)
1531 // Nothing to do in this case
1534 try_return( ntStatus);
1537 AFSAcquireShared( &pFcb->NPFcb->Resource,
1541 // Retrieve the buffer for the read request
1544 pBuffer = AFSLockSystemBuffer( Irp,
1545 pIrpSp->Parameters.Read.Length);
1547 if( pBuffer == NULL)
1550 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1551 AFS_TRACE_LEVEL_ERROR,
1552 "AFSShareRead Failed to map buffer on pipe %wZ\n",
1553 &pCcb->DirectoryCB->NameInformation.FileName);
1555 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1558 RtlZeroMemory( &stIoRequest,
1559 sizeof( AFSPipeIORequestCB));
1561 stIoRequest.RequestId = pCcb->RequestID;
1563 stIoRequest.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1565 stIoRequest.BufferLength = pIrpSp->Parameters.Read.Length;
1567 ulBytesReturned = pIrpSp->Parameters.Read.Length;
1570 // Issue the open request to the service
1573 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_READ,
1574 AFS_REQUEST_FLAG_SYNCHRONOUS,
1576 &pCcb->DirectoryCB->NameInformation.FileName,
1578 (void *)&stIoRequest,
1579 sizeof( AFSPipeIORequestCB),
1583 if( !NT_SUCCESS( ntStatus) &&
1584 ntStatus != STATUS_BUFFER_OVERFLOW)
1587 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1588 AFS_TRACE_LEVEL_ERROR,
1589 "AFSShareRead (%08lX) Failed service read Status %08lX\n",
1593 try_return( ntStatus);
1596 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
1597 AFS_TRACE_LEVEL_VERBOSE,
1598 "AFSShareRead Completed on pipe %wZ Length read %08lX Status %08lX\n",
1599 &pCcb->DirectoryCB->NameInformation.FileName,
1603 Irp->IoStatus.Information = ulBytesReturned;
1610 AFSReleaseResource( &pFcb->NPFcb->Resource);