ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

read.c
Go to the documentation of this file.
00001 /*************************************************************************
00002 *
00003 * File: read.c
00004 *
00005 * Module: Ext2 File System Driver (Kernel mode execution only)
00006 *
00007 * Description:
00008 *   Contains code to handle the "Read" dispatch entry point.
00009 *
00010 * Author: Manoj Paul Joseph
00011 *
00012 *
00013 *************************************************************************/
00014 
00015 #include            "ext2fsd.h"
00016 
00017 // define the file specific bug-check id
00018 #define         EXT2_BUG_CHECK_ID               EXT2_FILE_READ
00019 
00020 #define         DEBUG_LEVEL                     (DEBUG_TRACE_READ)
00021 
00022 
00023 /*************************************************************************
00024 *
00025 * Function: Ext2Read()
00026 *
00027 * Description:
00028 *   The I/O Manager will invoke this routine to handle a read
00029 *   request
00030 *
00031 * Expected Interrupt Level (for execution) :
00032 *
00033 *  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
00034 *   to be deferred to a worker thread context)
00035 *
00036 * Return Value: STATUS_SUCCESS/Error
00037 *
00038 *************************************************************************/
00039 NTSTATUS NTAPI Ext2Read(
00040 PDEVICE_OBJECT      DeviceObject,       // the logical volume device object
00041 PIRP                    Irp)                    // I/O Request Packet
00042 {
00043     NTSTATUS                RC = STATUS_SUCCESS;
00044     PtrExt2IrpContext   PtrIrpContext = NULL;
00045     BOOLEAN             AreWeTopLevel = FALSE;
00046     
00047     DebugTrace(DEBUG_TRACE_IRP_ENTRY,   "Read IRP Received...", 0);
00048 
00049     //  Ext2BreakPoint();
00050     
00051     FsRtlEnterFileSystem();
00052     ASSERT(DeviceObject);
00053     ASSERT(Irp);
00054 
00055     // set the top level context
00056     AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
00057 
00058     try
00059     {
00060         // get an IRP context structure and issue the request
00061         PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
00062         ASSERT(PtrIrpContext);
00063 
00064         RC = Ext2CommonRead(PtrIrpContext, Irp, TRUE);
00065 
00066     }
00067     except ( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) ) 
00068     {
00069 
00070         RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
00071 
00072         Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
00073     }
00074 
00075     if (AreWeTopLevel) 
00076     {
00077         IoSetTopLevelIrp(NULL);
00078     }
00079     
00080     FsRtlExitFileSystem();
00081     
00082     return(RC);
00083 }
00084 
00085 
00086 
00087 /*************************************************************************
00088 *
00089 * Function: Ext2CommonRead()
00090 *
00091 * Description:
00092 *   The actual work is performed here. This routine may be invoked in one
00093 *   of the two possible contexts:
00094 *   (a) in the context of a system worker thread
00095 *   (b) in the context of the original caller
00096 *
00097 * Expected Interrupt Level (for execution) :
00098 *
00099 *  IRQL_PASSIVE_LEVEL
00100 *
00101 * Return Value: STATUS_SUCCESS/Error
00102 *
00103 *************************************************************************/
00104 NTSTATUS NTAPI Ext2CommonRead(
00105 PtrExt2IrpContext           PtrIrpContext,
00106 PIRP                        PtrIrp,
00107 BOOLEAN                     FirstAttempt )
00108 {
00109     NTSTATUS                RC = STATUS_SUCCESS;
00110     PIO_STACK_LOCATION      PtrIoStackLocation = NULL;
00111     LARGE_INTEGER           ByteOffset;
00112     uint32                  ReadLength = 0, TruncatedReadLength = 0;
00113     uint32                  NumberBytesRead = 0;
00114     PFILE_OBJECT            PtrFileObject = NULL;
00115     PtrExt2FCB              PtrFCB = NULL;
00116     PtrExt2CCB              PtrCCB = NULL;
00117     PtrExt2VCB              PtrVCB = NULL;
00118     PtrExt2NTRequiredFCB    PtrReqdFCB = NULL;
00119     PERESOURCE              PtrResourceAcquired = NULL;
00120     PVOID                   PtrSystemBuffer = NULL;
00121     PVOID                   PtrPinnedReadBuffer = NULL;
00122 
00123     BOOLEAN                 CompleteIrp = TRUE;
00124     BOOLEAN                 PostRequest = FALSE;
00125 
00126     BOOLEAN                 CanWait = FALSE;
00127     BOOLEAN                 PagingIo = FALSE;
00128     BOOLEAN                 NonBufferedIo = FALSE;
00129     BOOLEAN                 SynchronousIo = FALSE;
00130     BOOLEAN                 ReadTruncated = FALSE;
00131 
00132     //  Used to cache the Single Indirect blocks pointed to by 
00133     //  the Double Indirect block
00134     PEXT2_SIBLOCKS          PtrDIArray = NULL;
00135     ULONG                   DIArrayCount = 0;
00136 
00137     //  Used to cache the Single Indirect blocks pointed to by 
00138     //  the Triple Indirect block
00139     PEXT2_SIBLOCKS          PtrTIArray = NULL;
00140     ULONG                   TIArrayCount = 0;
00141 
00142     EXT2_IO_RUN *           PtrIoRuns = NULL;
00143 
00144     ULONG   Start;
00145     ULONG   End;
00146     ULONG   LogicalBlockIndex;
00147     ULONG   BytesRemaining;
00148     ULONG   BytesReadSoFar;
00149     ULONG   LeftOver;
00150     ULONG   LogicalBlockSize;
00151     ULONG   PhysicalBlockSize;
00152 
00153     PBCB PtrPinnedSIndirectBCB = NULL;
00154     PBCB PtrPinnedDIndirectBCB = NULL;
00155     PBCB PtrPinnedTIndirectBCB = NULL;
00156 
00157     int Index;
00158 
00159     try 
00160     {
00161         try{
00162         // First, get a pointer to the current I/O stack location
00163         PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
00164         ASSERT(PtrIoStackLocation);
00165 
00166         // If this happens to be a MDL read complete request, then
00167         // there is not much processing that the FSD has to do.
00168         if (PtrIoStackLocation->MinorFunction & IRP_MN_COMPLETE) 
00169         {
00170             // Caller wants to tell the Cache Manager that a previously
00171             // allocated MDL can be freed.
00172             Ext2MdlComplete(PtrIrpContext, PtrIrp, PtrIoStackLocation, TRUE);
00173             // The IRP has been completed.
00174             CompleteIrp = FALSE;
00175             try_return(RC = STATUS_SUCCESS);
00176         }
00177 
00178         // If this is a request at IRQL DISPATCH_LEVEL, then post
00179         // the request (your FSD may choose to process it synchronously
00180         // if you implement the support correctly; obviously you will be
00181         // quite constrained in what you can do at such IRQL).
00182         if (PtrIoStackLocation->MinorFunction & IRP_MN_DPC) 
00183         {
00184             DebugTrace(DEBUG_TRACE_MISC,   " === Deferring Read ", 0 );
00185             CompleteIrp = FALSE;
00186             PostRequest = TRUE;
00187             try_return(RC = STATUS_PENDING);
00188         }
00189 
00190         PtrFileObject = PtrIoStackLocation->FileObject;
00191         ASSERT(PtrFileObject);
00192 
00193         // Get the FCB and CCB pointers
00194         Ext2GetFCB_CCB_VCB_FromFileObject ( 
00195             PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
00196 
00197         // Get some of the parameters supplied to us
00198         ByteOffset = PtrIoStackLocation->Parameters.Read.ByteOffset;
00199         ReadLength = PtrIoStackLocation->Parameters.Read.Length;
00200 
00201         CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
00202         PagingIo = ((PtrIrp->Flags & IRP_PAGING_IO) ? TRUE : FALSE);
00203         NonBufferedIo = ((PtrIrp->Flags & IRP_NOCACHE) ? TRUE : FALSE);
00204         SynchronousIo = ((PtrFileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE);
00205 
00206         if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
00207         {
00208             DebugTrace(DEBUG_TRACE_FILE_NAME,   " === Read File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
00209         }
00210         else
00211         {
00212             DebugTrace(DEBUG_TRACE_FILE_NAME,   " === Read File Name : -null-", 0);
00213         }
00214         
00215         DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->ByteCount           = 0x%8lx", PtrIoStackLocation->Parameters.Read.Length);
00216         DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->ByteOffset.LowPart  = 0x%8lx", PtrIoStackLocation->Parameters.Read.ByteOffset.LowPart);
00217         
00218         if( CanWait )
00219         {
00220             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->Can Wait ", 0 );
00221         }
00222         else
00223         {
00224             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->Can't Wait ", 0 );
00225         }
00226         
00227         if( PagingIo )
00228         {
00229             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->Paging Io ", 0 );
00230         }
00231         else
00232         {
00233             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->Not Paging Io", 0 );
00234         }
00235 
00236         if( SynchronousIo )
00237         {
00238             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->SynchronousIo ", 0 );
00239         }
00240         else
00241         {
00242             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->ASynchronousIo ", 0 );
00243         }
00244 
00245         if( NonBufferedIo )
00246         {
00247             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->NonBufferedIo", 0 );
00248         }
00249         else
00250         {
00251             DebugTrace(DEBUG_TRACE_READ_DETAILS,   "  ->BufferedIo", 0 );
00252         }
00253 
00254     
00255         if (ReadLength == 0) 
00256         {
00257             // a 0 byte read can be immediately succeeded
00258             try_return();
00259         }
00260 
00261         // Is this a read of the volume itself ?
00262         if ( ( !PtrFCB && PtrVCB ) || PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB )
00263         {
00264             //
00265             //  >>>>>>>>>>>     Volume Read     <<<<<<<<<<<<
00266             //
00267             // Yep, we need to send this on to the disk driver after
00268             //  validation of the offset and length.
00269 
00270             //  PtrVCB = (PtrExt2VCB)(PtrFCB);
00271 
00272             if (PtrVCB->VCBFlags & EXT2_FCB_PAGE_FILE ) 
00273             {
00274                 DebugTrace(DEBUG_TRACE_READ_DETAILS,  "[Read] *Volume Page File *", 0);
00275             }
00276 
00277             // Acquire the volume resource shared ...
00278 
00279             if( PtrFileObject )
00280             {
00281                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Read]", PtrFileObject);
00282             }
00283 
00284             if( PagingIo )
00285             {
00286                 DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire VCB Shared [Read]", 0);
00287                 DebugTraceState( "VCBPaging       AC:0x%LX   SW:0x%LX   EX:0x%LX   [Read]", PtrVCB->PagingIoResource.ActiveCount, PtrVCB->PagingIoResource.NumberOfExclusiveWaiters, PtrVCB->PagingIoResource.NumberOfSharedWaiters );
00288                 if (!ExAcquireResourceSharedLite(&(PtrVCB->PagingIoResource), FALSE )) 
00289                 {
00290                     // post the request to be processed in the context of a worker thread
00291                     DebugTrace(DEBUG_TRACE_MISC,   "*** VCBPaging Acquisition FAILED [Read]", 0);
00292                     CompleteIrp = FALSE;
00293                     PostRequest = TRUE;
00294                     try_return(RC = STATUS_PENDING);
00295                 }
00296                 DebugTrace(DEBUG_TRACE_MISC,  "*** VCBPaging Acquired [Read]", 0);
00297                 
00298                 PtrResourceAcquired = &(PtrVCB->PagingIoResource);
00299             }
00300             else
00301             {
00302                 DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire VCB Shared [Read]", 0);
00303                 DebugTraceState( "VCB       AC:0x%LX   SW:0x%LX   EX:0x%LX   [Read]", PtrVCB->VCBResource.ActiveCount, 
00304                     PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
00305                 if (!ExAcquireResourceSharedLite(&(PtrVCB->VCBResource), FALSE )) 
00306                 {
00307                     // post the request to be processed in the context of a worker thread
00308                     DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquisition FAILED [Read]", 0);
00309                     CompleteIrp = FALSE;
00310                     PostRequest = TRUE;
00311                     try_return(RC = STATUS_PENDING);
00312                 }
00313                 DebugTrace(DEBUG_TRACE_MISC,  "*** VCB Acquired [Read]", 0);
00314                 
00315                 PtrResourceAcquired = &(PtrVCB->VCBResource);
00316             }
00317             if( !PagingIo )
00318             {
00319                 if( PtrVCB->CommonVCBHeader.AllocationSize.QuadPart < ByteOffset.QuadPart )
00320                 {
00321                     RC = STATUS_END_OF_FILE;
00322                     NumberBytesRead = 0;
00323                     try_return();
00324                 }
00325             }
00326             if( PagingIo || NonBufferedIo )
00327             {
00328                 DebugTrace(DEBUG_TRACE_MISC,  "[Volume Read] PagingIo or NonBufferedIo ", 0);
00329                 CompleteIrp = FALSE;
00330 
00331                 RC = Ext2PassDownSingleReadWriteIRP (
00332                     PtrIrpContext, PtrIrp, PtrVCB, 
00333                     ByteOffset, ReadLength, SynchronousIo);
00334 
00335                 try_return();
00336             }
00337             else
00338             {
00339                 //  Buffer Control Block
00340                 PBCB        PtrBCB = NULL;
00341                 DebugTrace(DEBUG_TRACE_READ_DETAILS,  "[Volume Read] BufferedIo ", 0);
00342                 //
00343                 //  Let the cache manager worry about this read...
00344                 //  Pinned access should have been initiated.
00345                 //  But checking anyway...
00346                 //
00347                 ASSERT( PtrVCB->PtrStreamFileObject );
00348                 ASSERT( PtrVCB->PtrStreamFileObject->PrivateCacheMap );
00349                 
00350                 if (!CcMapData( PtrVCB->PtrStreamFileObject,
00351                     &ByteOffset,
00352                     ReadLength,
00353                     TRUE,
00354                     &PtrBCB,
00355                     &PtrPinnedReadBuffer) ) 
00356                 {
00357 
00358                     RC = STATUS_UNSUCCESSFUL;
00359                     NumberBytesRead = 0;
00360                     try_return();
00361                 }
00362                 else
00363                 {
00364                     PtrSystemBuffer = Ext2GetCallersBuffer(PtrIrp);
00365                     RtlCopyBytes( PtrSystemBuffer, PtrPinnedReadBuffer, ReadLength );
00366                     CcUnpinData( PtrBCB );
00367                     PtrBCB = NULL;
00368                     RC = STATUS_SUCCESS;
00369                     NumberBytesRead = ReadLength;
00370                     try_return();
00371 
00372                 }
00373             }
00374         }
00375 
00376 
00377         // If the read request is directed to a page file 
00378         // send the request directly to the disk driver. 
00379         // For requests directed to a page file, you have to trust
00380         // that the offsets will be set correctly by the VMM. You should not
00381         // attempt to acquire any FSD resources either.
00382 
00383         if (PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE) 
00384         {
00385             IoMarkIrpPending(PtrIrp);
00386             // You will need to set a completion routine before invoking
00387             // a lower level driver
00388             //  forward request directly to disk driver
00389             // Ext2PageFileIo(PtrIrpContext, PtrIrp);
00390             DebugTrace( DEBUG_TRACE_SPECIAL, "[Read] To a *Page File* - Not handled \ngoing into a hang...", 0);
00391             CompleteIrp = FALSE;
00392             try_return(RC = STATUS_PENDING);
00393         }
00394 
00395 
00396         //
00397         //  If this read is directed to a directory...
00398         //  Paging IO is allowed though...
00399         //
00400         if ( ( PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY ) &&  !PagingIo )
00401         {
00402             RC = STATUS_INVALID_DEVICE_REQUEST;
00403             try_return();
00404         }
00405 
00406         PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
00407 
00408         // Check whether the desired read can be allowed depending
00409         //  on any byte range locks that might exist. Note that for
00410         //  paging-io, no such checks should be performed.
00411         if (!PagingIo) 
00412         {
00413             //  Insert code to perform the check here ...
00414             //
00415             //  if (!Ext2CheckForByteLock(PtrFCB, PtrCCB, PtrIrp, PtrCurrentIoStackLocation)) 
00416             //  {
00417             //      try_return(RC = STATUS_FILE_LOCK_CONFLICT);
00418             //  }
00419         }
00420 
00421         // There are certain complications that arise when the same file stream
00422         // has been opened for cached and non-cached access. The FSD is then
00423         // responsible for maintaining a consistent view of the data seen by
00424         // the caller.
00425         // Also, it is possible for file streams to be mapped in both as data files
00426         // and as an executable. This could also lead to consistency problems since
00427         // there now exist two separate sections (and pages) containing file
00428         // information.
00429         // Read Chapter 10 for more information on the issues involved in
00430         // maintaining data consistency.
00431         // The test below flushes the data cached in system memory if the current
00432         // request madates non-cached access (file stream must be cached) and
00433         // (a) the current request is not paging-io which indicates it is not
00434         //       a recursive I/O operation OR originating in the Cache Manager
00435         // (b) OR the current request is paging-io BUT it did not originate via
00436         //       the Cache Manager (or is a recursive I/O operation) and we do
00437         //       have an image section that has been initialized.
00438 
00439 
00440 
00441         #define EXT2_REQ_NOT_VIA_CACHE_MGR(ptr) (!MmIsRecursiveIoFault() && ((ptr)->ImageSectionObject != NULL))
00442 
00443         if( NonBufferedIo && (PtrReqdFCB->SectionObject.DataSectionObject != NULL) )
00444         {
00445             if  (!PagingIo || (EXT2_REQ_NOT_VIA_CACHE_MGR(&(PtrReqdFCB->SectionObject)))) 
00446             {
00447                 CcFlushCache(&(PtrReqdFCB->SectionObject), &ByteOffset, ReadLength, &(PtrIrp->IoStatus));
00448                 // If the flush failed, return error to the caller
00449                 if (!NT_SUCCESS(RC = PtrIrp->IoStatus.Status)) 
00450                 {
00451                     try_return();
00452                 }
00453             }
00454         }
00455 
00456         //
00457         //  Synchronizing with other reads and writes...
00458         //  Acquire the appropriate FCB resource shared
00459         //
00460         if ( PagingIo ) 
00461         {
00462             // Try to acquire the FCB PagingIoResource shared
00463             if( PtrFileObject )
00464             {
00465                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Read]", PtrFileObject);
00466             }
00467             DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire FCBPaging Shared [Read]", 0);
00468             DebugTraceState( "FCBPaging AC:0x%LX   SW:0x%LX   EX:0x%LX   [Read]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
00469             if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->PagingIoResource), CanWait)) 
00470             {
00471                 DebugTrace(DEBUG_TRACE_MISC,   "*** FCBPaging Acquisition FAILED [Read]", 0);
00472 
00473                 CompleteIrp = FALSE;
00474                 PostRequest = TRUE;
00475                 try_return(RC = STATUS_PENDING);
00476             }
00477             
00478             DebugTrace(DEBUG_TRACE_MISC,   "*** FCBPaging Acquired [Read]", 0);
00479 
00480             // Remember the resource that was acquired
00481             PtrResourceAcquired = &(PtrReqdFCB->PagingIoResource);
00482         } 
00483         else 
00484         {
00485             // Try to acquire the FCB MainResource shared
00486             if( PtrFileObject )
00487             {
00488                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Read]", PtrFileObject);
00489             }
00490             DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire FCB Shared [Read]", 0);
00491             DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [Read]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
00492             if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait)) 
00493             {
00494                 DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [Read]", 0);
00495                 CompleteIrp = FALSE;
00496                 PostRequest = TRUE;
00497                 try_return(RC = STATUS_PENDING);
00498             }
00499             DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquired [Read]", 0);
00500             
00501             // Remember the resource that was acquired
00502             PtrResourceAcquired = &(PtrReqdFCB->MainResource);
00503         }
00504 
00505         //  Read in the File inode...
00506         Ext2InitializeFCBInodeInfo( PtrFCB );
00507 
00508         if (!PagingIo) 
00509         {
00510             LARGE_INTEGER  CurrentTime;
00511             KeQuerySystemTime( &CurrentTime );
00512             PtrFCB->LastAccessTime.QuadPart = CurrentTime.QuadPart;
00513         }
00514 
00515         // Validate start offset and length supplied.
00516         if (ByteOffset.QuadPart >= PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart )
00517         {
00518             // Starting offset is > file size
00519             try_return(RC = STATUS_END_OF_FILE);
00520         }
00521 
00522         /*
00523          * Round down the size of Paging I/O requests too. I'm not
00524          * sure if the FS driver is responsible for doing that, but
00525          * all other drivers I have seen do it.
00526          * -- Filip Navara, 18/08/2004
00527          */
00528         if ( ByteOffset.QuadPart + ReadLength > PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart )
00529         {
00530             //  Read going beyond the end of file...
00531             //  Adjusting the Read Length...
00532             ReadLength = (UINT)(PtrReqdFCB->CommonFCBHeader.FileSize.QuadPart - ByteOffset.QuadPart);
00533             if (PagingIo)
00534                 ReadLength = ROUND_TO_PAGES(ReadLength);
00535             ReadTruncated = TRUE;
00536         }
00537 
00538         // This is also a good place to set whether fast-io can be performed
00539         // on this particular file or not. Your FSD must make it's own
00540         // determination on whether or not to allow fast-io operations.
00541         // Commonly, fast-io is not allowed if any byte range locks exist
00542         // on the file or if oplocks prevent fast-io. Practically any reason
00543         // choosen by your FSD could result in your setting FastIoIsNotPossible
00544         // OR FastIoIsQuestionable instead of FastIoIsPossible.
00545         //
00546         // PtrReqdFCB->CommonFCBHeader.IsFastIoPossible = FastIoIsPossible;
00547 
00548         
00549         //  Branch here for cached vs non-cached I/O
00550 
00551         if (!NonBufferedIo) 
00552         {
00553             DebugTrace(DEBUG_TRACE_READ_DETAILS,  "[File Read] BufferedIo ", 0);
00554 
00555             // The caller wishes to perform cached I/O. Initiate caching if
00556             // this is the first cached I/O operation using this file object
00557             if (PtrFileObject->PrivateCacheMap == NULL) 
00558             {
00559                 // This is the first cached I/O operation. You must ensure
00560                 // that the FCB Common FCB Header contains valid sizes at this time
00561                 CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)),
00562                     FALSE,      // We will not utilize pin access for this file
00563                     &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
00564                     PtrCCB);        // The context used in callbacks
00565             }
00566 
00567             // Check and see if this request requires a MDL returned to the caller
00568             if (PtrIoStackLocation->MinorFunction & IRP_MN_MDL) 
00569             {
00570                 // Caller does want a MDL returned. Note that this mode
00571                 // implies that the caller is prepared to block
00572                 CcMdlRead(PtrFileObject, &ByteOffset, TruncatedReadLength, &(PtrIrp->MdlAddress), &(PtrIrp->IoStatus));
00573                 NumberBytesRead = PtrIrp->IoStatus.Information;
00574                 RC = PtrIrp->IoStatus.Status;
00575 
00576                 try_return();
00577             }
00578 
00579             // This is a regular run-of-the-mill cached I/O request. Let the
00580             // Cache Manager worry about it!
00581             // First though, we need a buffer pointer (address) that is valid
00582             PtrSystemBuffer = Ext2GetCallersBuffer(PtrIrp);
00583             ASSERT(PtrSystemBuffer);
00584 
00585             if (!CcCopyRead(PtrFileObject, &(ByteOffset), ReadLength, CanWait, PtrSystemBuffer, &(PtrIrp->IoStatus))) 
00586             {
00587                 // The caller was not prepared to block and data is not immediately
00588                 // available in the system cache
00589                 DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure. Cannot read without blocking...", 0);
00590                 CompleteIrp = FALSE;
00591                 PostRequest = TRUE;
00592             
00593                 // Mark Irp Pending ...
00594                 IoMarkIrpPending( PtrIrp );
00595                 RC = STATUS_PENDING;
00596                 try_return();
00597             }
00598 
00599             // We have the data
00600             RC = PtrIrp->IoStatus.Status;
00601             NumberBytesRead = PtrIrp->IoStatus.Information;
00602             try_return();
00603         }
00604         else // NonBuffered or Paged IO
00605         {
00606             LONGLONG    SingleIndirectBlockSize ;
00607             LONGLONG    DoubleIndirectBlockSize ;
00608             LONGLONG    TripleIndirectBlockSize ;
00609             LONGLONG    DirectBlockSize ;
00610 
00611             LONGLONG    NoOfDirectBlocks ;
00612             LONGLONG    NoOfSingleIndirectBlocks ;
00613             LONGLONG    NoOfDoubleIndirectBlocks ;
00614             LONGLONG    NoOfTripleIndirectBlocks ;
00615 
00616             ULONG * PtrPinnedSIndirectBlock = NULL;
00617             ULONG * PtrPinnedDIndirectBlock = NULL;
00618             ULONG * PtrPinnedTIndirectBlock = NULL;
00619 
00620             //  Used when reading a Triple Indirect Block...
00621             LONGLONG        FirstCachedDIBlockOffset = 0;
00622 
00623             //  Used when reading a Double Indirect Block...
00624             LONGLONG        FirstCachedSIBlockOffset = 0;
00625             
00626             DebugTrace(DEBUG_TRACE_MISC,  "[File Read] Paging IO or NonBufferedIo ", 0);
00627 
00628             //  Calculating where the read should start from...
00629             LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
00630             PhysicalBlockSize = PtrVCB->TargetDeviceObject->SectorSize;
00631 
00632             NoOfDirectBlocks =  EXT2_NDIR_BLOCKS ;
00633             NoOfSingleIndirectBlocks = LogicalBlockSize / sizeof( ULONG );
00634             NoOfDoubleIndirectBlocks = NoOfSingleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
00635             NoOfTripleIndirectBlocks = NoOfDoubleIndirectBlocks * LogicalBlockSize / sizeof( ULONG );
00636 
00637             DirectBlockSize =  LogicalBlockSize * NoOfDirectBlocks;
00638             SingleIndirectBlockSize = LogicalBlockSize * NoOfSingleIndirectBlocks;
00639             DoubleIndirectBlockSize = LogicalBlockSize * NoOfDoubleIndirectBlocks ;
00640             TripleIndirectBlockSize = LogicalBlockSize * NoOfTripleIndirectBlocks;
00641 
00642             LogicalBlockIndex = (ULONG)( ByteOffset.QuadPart / LogicalBlockSize);
00643 
00644             /*
00645             if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
00646             {
00647                 //
00648                 //  Handle Triple indirect blocks?
00649                 //  A Pop up will do for now...
00650                 //
00651                 UNICODE_STRING ErrorMessage;
00652                 Ext2CopyWideCharToUnicodeString( &ErrorMessage, L"Triple indirect blocks not supported as yet. - Ext2.sys" );
00653                 DebugTrace(DEBUG_TRACE_ERROR,   "@@@@@@@@  Triple indirect blocks need to be read in! \n@@@@@@@@  This is not supported as yet!", 0);
00654                 IoRaiseInformationalHardError(
00655                         IO_ERR_DRIVER_ERROR,
00656                         &ErrorMessage,
00657                         KeGetCurrentThread( ) );
00658 
00659                 Ext2DeallocateUnicodeString( &ErrorMessage );
00660 
00661                 RC = STATUS_INSUFFICIENT_RESOURCES;
00662                 try_return ( RC );
00663 
00664             }
00665             */
00666             if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize &&
00667                 ( ByteOffset.QuadPart < DirectBlockSize + SingleIndirectBlockSize ) )
00668             {
00669                 //
00670                 //  Single Indirect Blocks required...
00671                 //  Read in the single indirect blocks...
00672                 //
00673                 
00674                 LARGE_INTEGER VolumeByteOffset;
00675 
00676                 DebugTrace(DEBUG_TRACE_MISC,   "Reading in some Single Indirect Blocks", 0);
00677 
00678                 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize;
00679 
00680                 //
00681                 //  Asking the cache manager to oblige by pinning the single indirect block...
00682                 //
00683                 if (!CcMapData( PtrVCB->PtrStreamFileObject,
00684                    &VolumeByteOffset,
00685                    LogicalBlockSize,
00686                    CanWait,
00687                    &PtrPinnedSIndirectBCB,
00688                    (PVOID*)&PtrPinnedSIndirectBlock )) 
00689                 {
00690                     CompleteIrp = FALSE;
00691                     PostRequest = TRUE;
00692                 
00693                     // Mark Irp Pending ...
00694                     IoMarkIrpPending( PtrIrp );
00695                     RC = STATUS_PENDING;
00696                     try_return();
00697                     DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure while reading in volume meta data - Retrying", 0);
00698                 }
00699             }
00700             if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize + SingleIndirectBlockSize &&
00701                 ( ByteOffset.QuadPart ) < DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
00702             {
00703                 //
00704                 //  Double Indirect Blocks required...
00705                 //  Read in the double indirect blocks...
00706                 //
00707 
00708                 LONGLONG        StartIndirectBlock;
00709                 LONGLONG        EndIndirectBlock;
00710 
00711                 
00712 
00713                 LARGE_INTEGER VolumeByteOffset;
00714 
00715                 DebugTrace(DEBUG_TRACE_MISC,   "Reading in some Double Indirect Blocks", 0);
00716 
00717                 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize;
00718 
00719                 //
00720                 //  Asking the cache manager to oblige by pinning the double indirect block...
00721                 //
00722                 if (!CcMapData( PtrVCB->PtrStreamFileObject,
00723                    &VolumeByteOffset,
00724                    LogicalBlockSize,
00725                    CanWait,
00726                    &PtrPinnedDIndirectBCB,
00727                    (PVOID*)&PtrPinnedDIndirectBlock )) 
00728                 {
00729                     CompleteIrp = FALSE;
00730                     PostRequest = TRUE;
00731                 
00732                     // Mark Irp Pending ...
00733                     IoMarkIrpPending( PtrIrp );
00734                     RC = STATUS_PENDING;
00735                     try_return();
00736                     DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure while reading in volume meta data - Retrying", 0);
00737                 }
00738 
00739                 //  So far so good...
00740                 //  Now determine the single indirect blocks that will have to be read in...
00741                 if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize )
00742                 {
00743                     //  Request doesnot require any single indirect or direct blocks
00744                     StartIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize);
00745                     StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
00746                     StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
00747                 }
00748                 else
00749                 {
00750                     StartIndirectBlock = 0;
00751                 }
00752 
00753                 FirstCachedSIBlockOffset = (NoOfSingleIndirectBlocks*(StartIndirectBlock+1)) + NoOfDirectBlocks;
00754 
00755                 if( ByteOffset.QuadPart + ReadLength >= 
00756                     DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize)
00757                 {
00758                     EndIndirectBlock  = DoubleIndirectBlockSize;
00759                 }
00760                 else
00761                 {
00762                     EndIndirectBlock = ByteOffset.QuadPart + ReadLength - 
00763                                        (DirectBlockSize + SingleIndirectBlockSize);
00764                 }
00765                 EndIndirectBlock = Ext2Align64( EndIndirectBlock, LogicalBlockSize )/LogicalBlockSize ;
00766                 EndIndirectBlock = Ext2Align64( EndIndirectBlock, NoOfSingleIndirectBlocks )/NoOfSingleIndirectBlocks;
00767     
00768                 DIArrayCount = (ULONG)(EndIndirectBlock - StartIndirectBlock);
00769 
00770                 PtrDIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( DIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
00771                 {
00772                     ULONG   i;
00773 
00774                     for( i = 0; i < DIArrayCount; i++ )
00775                     {
00776                         VolumeByteOffset.QuadPart =  PtrPinnedDIndirectBlock[StartIndirectBlock+i] * LogicalBlockSize;
00777                         if (!CcMapData( PtrVCB->PtrStreamFileObject,
00778                            &VolumeByteOffset,
00779                            LogicalBlockSize,
00780                            CanWait,
00781                            &PtrDIArray[i].PtrBCB,
00782                            (PVOID*)&PtrDIArray[i].PtrSIBlocks)) 
00783                         {
00784                             CompleteIrp = FALSE;
00785                             PostRequest = TRUE;
00786                             IoMarkIrpPending( PtrIrp );
00787                             DIArrayCount = i;
00788                             try_return(RC = STATUS_PENDING);
00789 
00790                             DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure while reading in volume meta data - Retrying", 0);
00791                         }
00792                     }
00793                 }
00794             }
00795             
00796             if( ( ByteOffset.QuadPart + ReadLength ) > DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
00797             {
00798                 //
00799                 //  Triple Indirect Blocks required...
00800                 //  Read in the triple indirect blocks...
00801                 //
00802                 LONGLONG        StartTIndirectBlock;
00803                 LONGLONG        EndTIndirectBlock;
00804 
00805                 LONGLONG        StartDIndirectBlock;
00806                 LONGLONG        EndDIndirectBlock;
00807                 LONGLONG        StartIndirectBlock;
00808                 LONGLONG        EndIndirectBlock;
00809 
00810                 LONGLONG        ByteOffsetTillHere = 0;
00811 
00812                 PBCB    TempDIBCB;
00813                 LONG*   TempDIBuffer;
00814 
00815                 ULONG TIArrayIndex = 0;
00816 
00817                 LARGE_INTEGER VolumeByteOffset;
00818 
00819                 DebugTrace(DEBUG_TRACE_MISC,   "Reading in some Triple Indirect Blocks", 0);
00820 
00821                 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_TIND_BLOCK ] * LogicalBlockSize;
00822 
00823                 DebugTrace(DEBUG_TRACE_TRIPLE,   "ByteOffset = 0x%I64X", ByteOffset );
00824                 DebugTrace(DEBUG_TRACE_TRIPLE,   "ReadLength = 0x%lX", ReadLength );
00825                 DebugTrace(DEBUG_TRACE_TRIPLE,   "EXT2_TIND_BLOCK = 0x%lX", PtrFCB->IBlock[ EXT2_TIND_BLOCK ] );
00826                 //
00827                 //  Asking the cache manager to oblige by pinning the triple indirect block...
00828                 //
00829                 if (!CcMapData( PtrVCB->PtrStreamFileObject,
00830                    &VolumeByteOffset,
00831                    LogicalBlockSize,
00832                    CanWait,
00833                    &PtrPinnedTIndirectBCB,
00834                    (PVOID*)&PtrPinnedTIndirectBlock )) 
00835                 {
00836                     CompleteIrp = FALSE;
00837                     PostRequest = TRUE;
00838                 
00839                     // Mark Irp Pending ...
00840                     IoMarkIrpPending( PtrIrp );
00841                     RC = STATUS_PENDING;
00842                     try_return();
00843                     DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure while reading in volume meta data - Retrying", 0);
00844                 }
00845 
00846                 //  Determine the no of BCBs that need to be saved...
00847                 if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
00848                 {
00849                     StartTIndirectBlock = ByteOffset.QuadPart;
00850                 }
00851                 else
00852                 {
00853                     StartTIndirectBlock = DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize;
00854                 }
00855                 EndTIndirectBlock = ByteOffset.QuadPart + ReadLength;
00856                 TIArrayCount = (ULONG)( (EndTIndirectBlock - StartTIndirectBlock) / SingleIndirectBlockSize ) + 2;
00857 
00858                 
00859                 PtrTIArray = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( TIArrayCount * sizeof( EXT2_SIBLOCKS ) ) );
00860 
00861                 //  Now determine the double indirect blocks that will have to be read in...
00862                 if( ByteOffset.QuadPart >= DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize )
00863                 {
00864                     //  Request doesnot require any single indirect or direct blocks
00865                     StartDIndirectBlock = ByteOffset.QuadPart - (DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize);
00866                     StartDIndirectBlock = StartDIndirectBlock / LogicalBlockSize;
00867                     StartDIndirectBlock = StartDIndirectBlock / NoOfDoubleIndirectBlocks;
00868 
00869                     ByteOffsetTillHere = DirectBlockSize + SingleIndirectBlockSize + (DoubleIndirectBlockSize*(StartDIndirectBlock+1)) ;
00870                     //FirstCachedDIBlockOffset = ByteOffset.QuadPart / LogicalBlockSize;
00871                     FirstCachedDIBlockOffset = ByteOffsetTillHere / LogicalBlockSize;
00872                 }
00873                 else
00874                 {
00875                     ByteOffsetTillHere = DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize;
00876                     FirstCachedDIBlockOffset = ByteOffsetTillHere / LogicalBlockSize;
00877                     StartDIndirectBlock = 0;
00878                 }
00879 
00880                 DebugTrace(DEBUG_TRACE_TRIPLE,   "ByteOffsetTillHere = 0x%lX", ByteOffsetTillHere );
00881 
00882                 EndDIndirectBlock  = ByteOffset.QuadPart + ReadLength - 
00883                     (DirectBlockSize + SingleIndirectBlockSize + DoubleIndirectBlockSize);
00884                 EndDIndirectBlock = Ext2Align64( EndDIndirectBlock, LogicalBlockSize ) / LogicalBlockSize ;
00885                 EndDIndirectBlock = Ext2Align64( EndDIndirectBlock, NoOfDoubleIndirectBlocks ) / NoOfDoubleIndirectBlocks;
00886 
00887                 {
00888                     //  Reading in the necessary double indirect bocks...
00889                     ULONG   i;
00890                     LONGLONG Count = EndDIndirectBlock-StartDIndirectBlock;
00891 
00892                     for( i = 0; i < Count; i++, ByteOffsetTillHere += DoubleIndirectBlockSize)
00893                     {
00894                         VolumeByteOffset.QuadPart =  PtrPinnedTIndirectBlock[StartDIndirectBlock+i] * LogicalBlockSize;
00895                         
00896                         DebugTrace(DEBUG_TRACE_TRIPLE,   "Double VolOffset = 0x%I64X", VolumeByteOffset );
00897 
00898                         if( !CcMapData( PtrVCB->PtrStreamFileObject,
00899                            &VolumeByteOffset,
00900                            LogicalBlockSize,
00901                            CanWait,
00902                            &TempDIBCB,
00903                            (PVOID*)&TempDIBuffer) )
00904                         {
00905                             CompleteIrp = FALSE;
00906                             PostRequest = TRUE;
00907                             IoMarkIrpPending( PtrIrp );
00908                             try_return(RC = STATUS_PENDING);
00909                             DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure while reading in volume meta data - Retrying", 0);
00910                         }
00911                     
00912                         if( ByteOffset.QuadPart > ByteOffsetTillHere)
00913                         {
00914                             StartIndirectBlock = ByteOffset.QuadPart - (ByteOffsetTillHere);
00915                             StartIndirectBlock = StartIndirectBlock / LogicalBlockSize;
00916                             StartIndirectBlock = StartIndirectBlock / NoOfSingleIndirectBlocks;
00917 
00918                             if( TIArrayIndex == 0 )
00919                             {
00920                                 FirstCachedDIBlockOffset += StartIndirectBlock * NoOfSingleIndirectBlocks;
00921                             }
00922                         }
00923                         else
00924                         {
00925                             StartIndirectBlock = 0;
00926                         }
00927 
00928                         if( ByteOffset.QuadPart + ReadLength >= ByteOffsetTillHere + DoubleIndirectBlockSize)
00929                         {
00930                             EndIndirectBlock  = DoubleIndirectBlockSize;
00931                         }
00932                         else
00933                         {
00934                             EndIndirectBlock = ByteOffset.QuadPart + ReadLength - ByteOffsetTillHere;
00935                         }
00936                         EndIndirectBlock = Ext2Align64( EndIndirectBlock, LogicalBlockSize )/LogicalBlockSize ;
00937                         EndIndirectBlock = Ext2Align64( EndIndirectBlock, NoOfSingleIndirectBlocks )/NoOfSingleIndirectBlocks;
00938                     
00939                         {
00940                             ULONG   i;
00941                                 
00942                             for( i = 0; i < (EndIndirectBlock - StartIndirectBlock); i++ )
00943                             {
00944                                 VolumeByteOffset.QuadPart =  TempDIBuffer[StartIndirectBlock+i] * LogicalBlockSize;
00945                                 DebugTrace(DEBUG_TRACE_TRIPLE,   "Single VolOffset = 0x%I64X", VolumeByteOffset );
00946 
00947                                 if (!CcMapData( PtrVCB->PtrStreamFileObject,
00948                                    &VolumeByteOffset,
00949                                    LogicalBlockSize,
00950                                    CanWait,
00951                                    &PtrTIArray[ TIArrayIndex ].PtrBCB,
00952                                    (PVOID*)&PtrTIArray[ TIArrayIndex ].PtrSIBlocks)) 
00953                                 {
00954                                     CompleteIrp = FALSE;
00955                                     PostRequest = TRUE;
00956                                     IoMarkIrpPending( PtrIrp );
00957                                     DIArrayCount = i;
00958                                     try_return(RC = STATUS_PENDING);
00959 
00960                                     DebugTrace(DEBUG_TRACE_ASYNC,   "Cache read failiure while reading in volume meta data - Retrying", 0);
00961                                 }
00962                                 TIArrayIndex++;
00963                             }
00964                         }
00965                         CcUnpinData( TempDIBCB );
00966                         TempDIBCB = NULL;
00967                         TempDIBuffer = NULL;
00968                     }
00969                 }
00970                 TIArrayCount = TIArrayIndex;
00971                 
00972                 DebugTrace(DEBUG_TRACE_TRIPLE,   "TIArrayCount = %ld", TIArrayCount );
00973                 DebugTrace(DEBUG_TRACE_TRIPLE,   "FirstCachedDIBlockOffset = 0x%lX", FirstCachedDIBlockOffset );
00974             }
00975 
00976 
00977             //  
00978             //  Allocating memory for IO Runs
00979             //
00980             Index = ( (ReadLength - 2) / LogicalBlockSize + 2 );
00981             PtrIoRuns = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( Index * sizeof( EXT2_IO_RUN) )  );
00982 
00983 
00984             Start = (ULONG) ( ByteOffset.QuadPart - (LogicalBlockSize * LogicalBlockIndex) );
00985             BytesRemaining = (ULONG)( LogicalBlockSize * (LogicalBlockIndex +1) - ByteOffset.QuadPart );
00986 
00987             if( ReadLength > BytesRemaining )
00988             {
00989                 End = Start + BytesRemaining;
00990             }
00991             else
00992             {
00993                 End = Start + ReadLength;
00994             }
00995             BytesReadSoFar = 0;
00996 
00997             Index = 0;
00998             DebugTrace(DEBUG_TRACE_MISC, "\nDetermining the read IRPs that have to be passed down...", 0);
00999             
01000             while( 1 )
01001             {
01002                 BytesReadSoFar += (End-Start);
01003                 if( LogicalBlockIndex < NoOfDirectBlocks )
01004                 {
01005                     //  Direct Block
01006                     PtrIoRuns[ Index ].LogicalBlock = PtrFCB->IBlock[ LogicalBlockIndex ];
01007                 }
01008                 else if( LogicalBlockIndex < (NoOfSingleIndirectBlocks + NoOfDirectBlocks) )
01009                 {
01010                     //  Single Indirect Block
01011                     PtrIoRuns[ Index ].LogicalBlock = PtrPinnedSIndirectBlock[ LogicalBlockIndex - NoOfDirectBlocks ];
01012                 }
01013                 else if( LogicalBlockIndex < (NoOfDoubleIndirectBlocks + NoOfSingleIndirectBlocks + NoOfDirectBlocks)  )
01014                 {
01015                     LONGLONG BlockNo;
01016                     LONGLONG IBlockIndex;
01017                     LONGLONG BlockIndex;
01018 
01019                     BlockNo     = LogicalBlockIndex - FirstCachedSIBlockOffset;
01020                     IBlockIndex = BlockNo / NoOfSingleIndirectBlocks;
01021                     BlockIndex  = BlockNo % NoOfSingleIndirectBlocks;
01022 
01023                     //  Double Indirect Block
01024                     PtrIoRuns[ Index ].LogicalBlock = 
01025                         PtrDIArray[ IBlockIndex ].PtrSIBlocks[ BlockIndex ];
01026                 }
01027                 else
01028                 {
01029                     //  Triple Indirect Block
01030                     LONGLONG BlockNo;
01031                     LONGLONG IBlockIndex;
01032                     LONGLONG BlockIndex;
01033                     BlockNo     = LogicalBlockIndex - FirstCachedDIBlockOffset;
01034                     IBlockIndex = BlockNo / NoOfSingleIndirectBlocks;
01035                     BlockIndex  = BlockNo % NoOfSingleIndirectBlocks;
01036 
01037                     DbgPrint( "\nBlock No : 0x%I64X   IBlockIndex = 0x%I64X   BlockIndex = 0x%I64X", BlockNo, IBlockIndex, BlockIndex);
01038 
01039                     if( IBlockIndex >= TIArrayCount )
01040                     {
01041                         Ext2BreakPoint();
01042                     }
01043                     if( BlockIndex >= LogicalBlockSize )
01044                     {
01045                         Ext2BreakPoint();
01046                     }
01047 
01048                     PtrIoRuns[ Index ].LogicalBlock = PtrTIArray[ IBlockIndex ].PtrSIBlocks[ BlockIndex ];
01049                     DbgPrint( "LogicalBlock = 0x%lX", PtrIoRuns[ Index ].LogicalBlock );
01050                 }
01051 
01052                 if( PtrIoRuns[ Index ].LogicalBlock == 0 )
01053                 {
01054                     //
01055                     //  Something is wrong...
01056                     //
01057                     //Ext2BreakPoint();
01058                     Index--;
01059                     break;
01060 
01061                 }
01062 
01063 
01064                 PtrIoRuns[ Index ].StartOffset = Start;
01065                 PtrIoRuns[ Index ].EndOffset = End;
01066                 PtrIoRuns[ Index ].PtrAssociatedIrp = NULL;
01067 
01068                 DebugTrace( DEBUG_TRACE_MISC, "  Index = (%ld)", LogicalBlockIndex );
01069                 DebugTrace( DEBUG_TRACE_MISC, "  Logical Block = (0x%lX)", PtrIoRuns[ Index ].LogicalBlock );
01070                 DebugTrace( DEBUG_TRACE_MISC, "  Start = (0x%lX)", Start );
01071                 DebugTrace( DEBUG_TRACE_MISC, "  End = (0x%lX)  ", End );
01072                 DebugTrace( DEBUG_TRACE_MISC, "  Bytes read (0x%lX)", BytesReadSoFar );
01073                  
01074                 
01075 
01076                 if( BytesReadSoFar >= ReadLength )
01077                     break;
01078                 LogicalBlockIndex++;
01079                 Start = 0;
01080                 LeftOver = ReadLength - BytesReadSoFar;
01081                 if( LeftOver > LogicalBlockSize )
01082                     End = LogicalBlockSize;
01083                 else
01084                     End = LeftOver;
01085                 //  Loop over to make the read request...
01086                 Index++;
01087             }
01088             //
01089             //  Unpin the Indirect Blocks
01090             //
01091             if( PtrPinnedSIndirectBCB )
01092             {
01093                 CcUnpinData( PtrPinnedSIndirectBCB  );
01094                 PtrPinnedSIndirectBCB = NULL;
01095                 PtrPinnedSIndirectBlock = NULL;
01096             }
01097 
01098             if( PtrPinnedDIndirectBCB )
01099             {
01100                 CcUnpinData( PtrPinnedDIndirectBCB );
01101                 PtrPinnedDIndirectBCB = NULL;
01102                 PtrPinnedDIndirectBlock = NULL;
01103             }
01104             
01105             if( PtrPinnedTIndirectBCB)
01106             {
01107                 CcUnpinData( PtrPinnedTIndirectBCB);
01108                 PtrPinnedTIndirectBCB = NULL;
01109                 PtrPinnedTIndirectBlock = NULL;
01110             }
01111             
01112             if ( PtrDIArray )
01113             {
01114                 ULONG   i;
01115                 for( i = 0; i < DIArrayCount; i++ )
01116                 {
01117                     CcUnpinData( PtrDIArray->PtrBCB );
01118                 }
01119                 DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Read]", PtrDIArray );
01120                 ExFreePool( PtrDIArray );
01121                 PtrDIArray = NULL;
01122             }           
01123             if ( PtrTIArray )
01124             {
01125                 ULONG   i;
01126                 for( i = 0; i < TIArrayCount; i++ )
01127                 {
01128                     CcUnpinData( PtrTIArray->PtrBCB );
01129                 }
01130                 DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Read]", PtrTIArray );
01131                 ExFreePool( PtrTIArray );
01132                 PtrTIArray = NULL;
01133             }   
01134             //
01135             //  Pass down Associated IRPs to the Target Device Driver...
01136             //
01137             DebugTrace( DEBUG_TRACE_MISC, "Passing down the Read IRPs to the disk driver...", 0 );
01138 
01139             RC = Ext2PassDownMultiReadWriteIRP( PtrIoRuns, Index+1, ReadLength, PtrIrpContext, PtrFCB, SynchronousIo );
01140             
01141             //
01142             //  Irp will be completed automatically 
01143             //  when all the Associated IRPs are completed
01144             //
01145             if( RC == STATUS_SUCCESS || RC == STATUS_PENDING )
01146             {
01147                 CompleteIrp = FALSE;    
01148             }
01149             try_return();
01150         
01151         }
01152         try_exit:   NOTHING;
01153         }
01154         except (EXCEPTION_EXECUTE_HANDLER) 
01155         {
01156             DebugTrace(DEBUG_TRACE_ERROR,   "@@@@@@@@  Exception Handler", 0);
01157         }
01158     }
01159     finally 
01160     {
01161         if ( PtrIoRuns )
01162         {
01163             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Read]", PtrIoRuns );
01164             ExFreePool( PtrIoRuns );
01165         }
01166         //
01167         //  Unpin the Indirect Blocks
01168         //
01169         if( PtrPinnedSIndirectBCB )
01170         {
01171             CcUnpinData( PtrPinnedSIndirectBCB  );
01172             PtrPinnedSIndirectBCB = NULL;
01173         }
01174 
01175         if( PtrPinnedDIndirectBCB )
01176         {
01177             CcUnpinData( PtrPinnedDIndirectBCB );
01178             PtrPinnedDIndirectBCB = NULL;
01179         }
01180         if( PtrPinnedTIndirectBCB )
01181         {
01182             CcUnpinData( PtrPinnedTIndirectBCB );
01183             PtrPinnedTIndirectBCB = NULL;
01184         }
01185 
01186         if ( PtrDIArray )
01187         {
01188             ULONG   i;
01189             for( i = 0; i < DIArrayCount; i++ )
01190             {
01191                 CcUnpinData( PtrDIArray->PtrBCB );
01192             }
01193             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Read]", PtrDIArray );
01194             ExFreePool( PtrDIArray );
01195         }
01196 
01197         if ( PtrTIArray )
01198         {
01199             ULONG   i;
01200             for( i = 0; i < TIArrayCount; i++ )
01201             {
01202                 CcUnpinData( PtrTIArray->PtrBCB );
01203             }
01204             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Read]", PtrTIArray );
01205             ExFreePool( PtrTIArray );
01206         }
01207 
01208         // Release any resources acquired here ...
01209         if (PtrResourceAcquired) 
01210         {
01211             Ext2ReleaseResource(PtrResourceAcquired);
01212             
01213             DebugTraceState( "Resource     AC:0x%LX   SW:0x%LX   EX:0x%LX   [Read]", 
01214                 PtrResourceAcquired->ActiveCount, 
01215                 PtrResourceAcquired->NumberOfExclusiveWaiters, 
01216                 PtrResourceAcquired->NumberOfSharedWaiters );
01217 
01218             if( PtrFileObject )
01219             {
01220                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Read]", PtrFileObject);
01221             }
01222             if( PtrVCB && PtrResourceAcquired == &(PtrVCB->VCBResource) )
01223             {
01224                 DebugTrace(DEBUG_TRACE_MISC,  "*** VCB Released [Read]", 0);
01225             }
01226             else if( PtrVCB && PtrResourceAcquired == &(PtrVCB->PagingIoResource ) )
01227             {
01228                 DebugTrace(DEBUG_TRACE_MISC,  "*** VCBPaging Released [Read]", 0);
01229             }
01230             else if( PtrReqdFCB && PtrResourceAcquired == &(PtrReqdFCB->PagingIoResource) )
01231             {
01232                 DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Paging Resource Released [Read]", 0);
01233             }
01234             else if(PtrReqdFCB && PtrResourceAcquired == &(PtrReqdFCB->MainResource) )
01235             {
01236                 DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Resource Released [Read]", 0);
01237             }
01238             else
01239             {
01240                 DebugTrace(DEBUG_TRACE_MISC,  "*** Unknown Resource Released [Read]", 0);
01241             }
01242 
01243             PtrResourceAcquired = NULL;
01244         }
01245 
01246         // Post IRP if required
01247         if ( PostRequest ) 
01248         {
01249 
01250             // Implement a routine that will queue up the request to be executed
01251             // later (asynchronously) in the context of a system worker thread.
01252             // See Chapter 10 for details.
01253 
01254             // Lock the callers buffer here. Then invoke a common routine to
01255             // perform the post operation.
01256             if (!(PtrIoStackLocation->MinorFunction & IRP_MN_MDL)) 
01257             {
01258                 RC = Ext2LockCallersBuffer(PtrIrp, TRUE, ReadLength);
01259                 ASSERT(NT_SUCCESS(RC));
01260             }
01261 
01262             // Perform the post operation which will mark the IRP pending
01263             // and will return STATUS_PENDING back to us
01264             RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
01265         }
01266         else if (CompleteIrp && !(RC == STATUS_PENDING)) 
01267         {
01268             // For synchronous I/O, the FSD must maintain the current byte offset
01269             // Do not do this however, if I/O is marked as paging-io
01270             if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) 
01271             {
01272                 PtrFileObject->CurrentByteOffset = RtlLargeIntegerAdd(ByteOffset, RtlConvertUlongToLargeInteger((unsigned long)NumberBytesRead));
01273             }
01274 
01275             // If the read completed successfully and this was not a paging-io
01276             // operation, set a flag in the CCB that indicates that a read was
01277             // performed and that the file time should be updated at cleanup
01278             if (NT_SUCCESS(RC) && !PagingIo) 
01279             {
01280                 Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_ACCESSED);
01281             }
01282 
01283             // Can complete the IRP here if no exception was encountered
01284             if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION)) 
01285             {
01286                 
01287                 PtrIrp->IoStatus.Status = RC;
01288                 PtrIrp->IoStatus.Information = NumberBytesRead;
01289 
01290                 // Free up the Irp Context
01291                 Ext2ReleaseIrpContext(PtrIrpContext);
01292     
01293                 // complete the IRP
01294                 IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
01295             }
01296         } // can we complete the IRP ?
01297         else
01298         {
01299             // Free up the Irp Context
01300             Ext2ReleaseIrpContext(PtrIrpContext);
01301         }
01302     } // end of "finally" processing
01303 
01304     return(RC);
01305 }
01306 
01307 
01308 
01309 
01310 /*************************************************************************
01311 *
01312 * Function: Ext2GetCallersBuffer()
01313 *
01314 * Description:
01315 *   Obtain a pointer to the caller's buffer.
01316 *
01317 * Expected Interrupt Level (for execution) :
01318 *
01319 *  IRQL_PASSIVE_LEVEL
01320 *
01321 * Return Value: STATUS_SUCCESS/Error
01322 *
01323 *************************************************************************/
01324 void * NTAPI Ext2GetCallersBuffer (
01325         PIRP  PtrIrp )
01326 {
01327     void    * ReturnedBuffer = NULL;
01328 
01329     // If an MDL is supplied, use it.
01330     if (PtrIrp->MdlAddress) 
01331     {
01332         ReturnedBuffer = MmGetSystemAddressForMdl(PtrIrp->MdlAddress);
01333     } 
01334     else 
01335     {
01336         ReturnedBuffer = PtrIrp->UserBuffer;
01337     }
01338 
01339     return (ReturnedBuffer);
01340 }
01341 
01342 
01343 
01344 /*************************************************************************
01345 *
01346 * Function: Ext2LockCallersBuffer()
01347 *
01348 * Description:
01349 *   Obtain a MDL that describes the buffer. Lock pages for I/O
01350 *
01351 * Expected Interrupt Level (for execution) :
01352 *
01353 *  IRQL_PASSIVE_LEVEL
01354 *
01355 * Return Value: STATUS_SUCCESS/Error
01356 *
01357 *************************************************************************/
01358 NTSTATUS NTAPI Ext2LockCallersBuffer(
01359 PIRP                PtrIrp,
01360 BOOLEAN         IsReadOperation,
01361 uint32          Length)
01362 {
01363     NTSTATUS            RC = STATUS_SUCCESS;
01364     PMDL                PtrMdl = NULL;
01365 
01366     ASSERT(PtrIrp);
01367     
01368     try 
01369     {
01370         // Is a MDL already present in the IRP
01371         if( !(PtrIrp->MdlAddress) )
01372         {
01373             // Allocate a MDL
01374             if (!(PtrMdl = IoAllocateMdl(PtrIrp->UserBuffer, Length, FALSE, FALSE, PtrIrp))) 
01375             {
01376                 RC = STATUS_INSUFFICIENT_RESOURCES;
01377                 try_return();
01378             }
01379 
01380             // Probe and lock the pages described by the MDL
01381             // We could encounter an exception doing so, swallow the exception
01382             // NOTE: The exception could be due to an unexpected (from our
01383             // perspective), invalidation of the virtual addresses that comprise
01384             // the passed in buffer
01385             try 
01386             {
01387                 MmProbeAndLockPages(PtrMdl, PtrIrp->RequestorMode, (IsReadOperation ? IoWriteAccess:IoReadAccess));
01388             } 
01389             except(EXCEPTION_EXECUTE_HANDLER) 
01390             {
01391                 RC = STATUS_INVALID_USER_BUFFER;
01392             }
01393         }
01394 
01395         try_exit:   NOTHING;
01396 
01397     } 
01398     finally 
01399     {
01400         if (!NT_SUCCESS(RC) && PtrMdl) 
01401         {
01402             IoFreeMdl(PtrMdl);
01403             // You MUST NULL out the MdlAddress field in the IRP after freeing
01404             // the MDL, else the I/O Manager will also attempt to free the MDL
01405             // pointed to by that field during I/O completion. Obviously, the
01406             // pointer becomes invalid once you free the allocated MDL and hence
01407             // you will encounter a system crash during IRP completion.
01408             PtrIrp->MdlAddress = NULL;
01409         }
01410     }
01411 
01412     return(RC);
01413 }
01414 
01415 
01416 
01417 /*************************************************************************
01418 *
01419 * Function: Ext2MdlComplete()
01420 *
01421 * Description:
01422 *   Tell Cache Manager to release MDL (and possibly flush).
01423 *
01424 * Expected Interrupt Level (for execution) :
01425 *
01426 *  IRQL_PASSIVE_LEVEL
01427 *
01428 * Return Value: None.
01429 *
01430 *************************************************************************/
01431 void NTAPI Ext2MdlComplete(
01432     PtrExt2IrpContext           PtrIrpContext,
01433     PIRP                        PtrIrp,
01434     PIO_STACK_LOCATION          PtrIoStackLocation,
01435     BOOLEAN                     ReadCompletion)
01436 {
01437 
01438     NTSTATUS                    RC = STATUS_SUCCESS;
01439     PFILE_OBJECT            PtrFileObject = NULL;
01440 
01441     PtrFileObject = PtrIoStackLocation->FileObject;
01442     ASSERT(PtrFileObject);
01443 
01444     // Not much to do here.
01445     if( ReadCompletion ) 
01446     {
01447         CcMdlReadComplete( PtrFileObject, PtrIrp->MdlAddress );
01448     } 
01449     else 
01450     {
01451         // The Cache Manager needs the byte offset in the I/O stack location.
01452         CcMdlWriteComplete( PtrFileObject, &(PtrIoStackLocation->Parameters.Write.ByteOffset), PtrIrp->MdlAddress );
01453     }
01454 
01455     // Clear the MDL address field in the IRP so the IoCompleteRequest()
01456     // does not try to play around with the MDL.
01457     PtrIrp->MdlAddress = NULL;
01458 
01459     // Free up the Irp Context.
01460     Ext2ReleaseIrpContext(PtrIrpContext);
01461 
01462     // Complete the IRP.
01463     PtrIrp->IoStatus.Status = RC;
01464     PtrIrp->IoStatus.Information = 0;
01465     IoCompleteRequest(PtrIrp, IO_NO_INCREMENT);
01466 
01467     return;
01468 }

Generated on Sat May 26 2012 04:26:20 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.