Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenread.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
1.7.6.1
|