Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

read.c File Reference

#include "UdfProcs.h"

Go to the source code of this file.

Defines

#define BugCheckFileId   (UDFS_BUG_CHECK_READ)
#define Dbg   (UDFS_DEBUG_LEVEL_READ)
#define SafeZeroMemory(IC, AT, BYTE_COUNT)
#define READ_AHEAD_GRANULARITY   (0x10000)

Functions

NTSTATUS UdfCommonRead (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)


Define Documentation

#define BugCheckFileId   (UDFS_BUG_CHECK_READ)
 

Definition at line 28 of file udfs/read.c.

#define Dbg   (UDFS_DEBUG_LEVEL_READ)
 

Definition at line 34 of file udfs/read.c.

#define READ_AHEAD_GRANULARITY   (0x10000)
 

Definition at line 60 of file udfs/read.c.

Referenced by UdfCommonRead().

#define SafeZeroMemory IC,
AT,
BYTE_COUNT   ) 
 

Value:

{ \ try { \ RtlZeroMemory( (AT), (BYTE_COUNT) ); \ } except( EXCEPTION_EXECUTE_HANDLER ) { \ UdfRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \ } \ }

Definition at line 48 of file udfs/read.c.

Referenced by UdfCommonRead().


Function Documentation

NTSTATUS UdfCommonRead IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp
 

Definition at line 68 of file udfs/read.c.

References Add2Ptr, ASSERT, BooleanFlagOn, BytesFromSectors, _UDF_DATA::CacheManagerCallbacks, CcCopyRead(), CcInitializeCacheMap(), CcMdlRead(), CcSetReadAheadGranularity(), ClearFlag, _FILE_OBJECT::CurrentByteOffset, DebugUnwind, _FCB::EmbeddedOffset, _FCB::EmbeddedVsn, ExGetCurrentResourceThread, FALSE, FCB_STATE_EMBEDDED_DATA, _FCB::FcbState, _IO_STACK_LOCATION::FileObject, FlagOn, _IRP::Flags, _FILE_OBJECT::Flags, FO_SYNCHRONOUS_IO, FsRtlCheckLockForReadAccess(), FsRtlCheckOplock(), FsRtlNormalizeNtstatus(), IoGetCurrentIrpStackLocation, IoIsErrorUserInduced, _IRP::IoStatus, Irp, IRP_CONTEXT_FLAG_ALLOC_IO, IRP_CONTEXT_FLAG_WAIT, IRP_MN_MDL, IRP_NOCACHE, IRP_PAGING_IO, KeInitializeEvent, _IRP::MdlAddress, _VCB::MetadataFcb, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PCC_FILE_SIZES, _FILE_OBJECT::PrivateCacheMap, READ_AHEAD_GRANULARITY, SafeZeroMemory, SectorAlign, SectorOffset, SetFlag, Status, SynchronousIo, TRUE, try_leave, TYPE_OF_OPEN, UDF_IO_CONTEXT, UdfAcquireFileShared, UdfAcquireFileSharedStarveExclusive, UdfAllocateIoContext, UdfCompleteRequest(), UdfData, UdfDecodeFileObject(), UdfFsdPostRequest(), UdfMapUserBuffer, UdfNonCachedRead(), UdfNormalizeAndRaiseStatus(), UdfOplockComplete(), UdfPrePostIrp(), UdfRaiseStatus(), UdfReleaseFile, UdfVerifyFcbOperation(), UnopenedFileObject, UserDirectoryOpen, UserFileOpen, UserVolumeOpen, and _FCB::Vcb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

00075 : 00076 00077 This is the common entry point for NtReadFile calls. For synchronous requests, 00078 CommonRead will complete the request in the current thread. If not 00079 synchronous the request will be passed to the Fsp if there is a need to 00080 block. 00081 00082 Arguments: 00083 00084 Irp - Supplies the Irp to process 00085 00086 Return Value: 00087 00088 NTSTATUS - The result of this operation. 00089 00090 --*/ 00091 00092 { 00093 NTSTATUS Status; 00094 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 00095 00096 TYPE_OF_OPEN TypeOfOpen; 00097 PFCB Fcb; 00098 PCCB Ccb; 00099 PVCB Vcb; 00100 00101 BOOLEAN Wait; 00102 ULONG PagingIo; 00103 ULONG SynchronousIo; 00104 ULONG NonCachedIo; 00105 00106 LONGLONG StartingOffset; 00107 LONGLONG ByteRange; 00108 ULONG ByteCount; 00109 ULONG ReadByteCount; 00110 ULONG OriginalByteCount; 00111 00112 PVOID SystemBuffer, UserBuffer; 00113 00114 BOOLEAN ReleaseFile = TRUE; 00115 00116 PFILE_OBJECT MappingFileObject; 00117 00118 UDF_IO_CONTEXT LocalIoContext; 00119 00120 PAGED_CODE(); 00121 00122 // 00123 // If this is a zero length read then return SUCCESS immediately. 00124 // 00125 00126 if (IrpSp->Parameters.Read.Length == 0) { 00127 00128 UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); 00129 return STATUS_SUCCESS; 00130 } 00131 00132 // 00133 // Decode the file object and verify we support read on this. It 00134 // must be a user file, stream file or volume file (for a data disk). 00135 // 00136 00137 TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb ); 00138 00139 Vcb = Fcb->Vcb; 00140 00141 if ((TypeOfOpen == UnopenedFileObject) || (TypeOfOpen == UserDirectoryOpen)) { 00142 00143 UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST ); 00144 return STATUS_INVALID_DEVICE_REQUEST; 00145 } 00146 00147 // 00148 // Examine our input parameters to determine if this is noncached and/or 00149 // a paging io operation. 00150 // 00151 00152 Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ); 00153 PagingIo = FlagOn( Irp->Flags, IRP_PAGING_IO ); 00154 NonCachedIo = FlagOn( Irp->Flags, IRP_NOCACHE ); 00155 SynchronousIo = FlagOn( IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO ); 00156 00157 // 00158 // Extract the range of the Io. 00159 // 00160 00161 StartingOffset = IrpSp->Parameters.Read.ByteOffset.QuadPart; 00162 OriginalByteCount = ByteCount = IrpSp->Parameters.Read.Length; 00163 00164 ByteRange = StartingOffset + ByteCount; 00165 00166 // 00167 // Make sure that Dasd access is always non-cached. 00168 // 00169 00170 if (TypeOfOpen == UserVolumeOpen) { 00171 00172 NonCachedIo = TRUE; 00173 } 00174 00175 // 00176 // Acquire the file shared to perform the read. If we are doing paging IO, 00177 // it may be the case that we would have a deadlock imminent because we may 00178 // block on shared access, so starve out any exclusive waiters. This requires 00179 // a degree of caution - we believe that any paging IO bursts will recede and 00180 // allow the exclusive waiter in. 00181 // 00182 00183 if (PagingIo) { 00184 00185 UdfAcquireFileSharedStarveExclusive( IrpContext, Fcb ); 00186 00187 } else { 00188 00189 UdfAcquireFileShared( IrpContext, Fcb ); 00190 } 00191 00192 // 00193 // Use a try-finally to facilitate cleanup. 00194 // 00195 00196 try { 00197 00198 // 00199 // Verify the Fcb. 00200 // 00201 00202 UdfVerifyFcbOperation( IrpContext, Fcb ); 00203 00204 // 00205 // If this is a user request then verify the oplock and filelock state. 00206 // 00207 00208 if (TypeOfOpen == UserFileOpen) { 00209 00210 // 00211 // We check whether we can proceed 00212 // based on the state of the file oplocks. 00213 // 00214 00215 Status = FsRtlCheckOplock( &Fcb->Oplock, 00216 Irp, 00217 IrpContext, 00218 UdfOplockComplete, 00219 UdfPrePostIrp ); 00220 00221 // 00222 // If the result is not STATUS_SUCCESS then the Irp was completed 00223 // elsewhere. 00224 // 00225 00226 if (Status != STATUS_SUCCESS) { 00227 00228 Irp = NULL; 00229 IrpContext = NULL; 00230 00231 try_leave( Status ); 00232 } 00233 00234 if (!PagingIo && 00235 (Fcb->FileLock != NULL) && 00236 !FsRtlCheckLockForReadAccess( Fcb->FileLock, Irp )) { 00237 00238 try_leave( Status = STATUS_FILE_LOCK_CONFLICT ); 00239 } 00240 } 00241 00242 // 00243 // Complete the request if it begins beyond the end of file. 00244 // 00245 00246 if (StartingOffset >= Fcb->FileSize.QuadPart) { 00247 00248 try_leave( Status = STATUS_END_OF_FILE ); 00249 } 00250 00251 // 00252 // Truncate the read if it extends beyond the end of the file. 00253 // 00254 00255 if (ByteRange > Fcb->FileSize.QuadPart) { 00256 00257 ByteCount = (ULONG) (Fcb->FileSize.QuadPart - StartingOffset); 00258 ByteRange = Fcb->FileSize.QuadPart; 00259 } 00260 00261 // 00262 // Now if the data is embedded in the ICB, map through the metadata 00263 // stream to retrieve the bytes. 00264 // 00265 00266 if (FlagOn( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA )) { 00267 00268 // 00269 // The metadata stream better be here by now. 00270 // 00271 00272 ASSERT( Vcb->MetadataFcb->FileObject != NULL ); 00273 00274 // 00275 // Bias our starting offset by the offset of the ICB in the metadata 00276 // stream plus the offset of the data bytes in that ICB. Obviously, 00277 // we aren't doing non-cached IO here. 00278 // 00279 00280 StartingOffset += (BytesFromSectors( Vcb, Fcb->EmbeddedVsn ) + Fcb->EmbeddedOffset); 00281 MappingFileObject = Vcb->MetadataFcb->FileObject; 00282 NonCachedIo = FALSE; 00283 00284 // 00285 // We are mapping through the caller's fileobject 00286 // 00287 00288 } else { 00289 00290 MappingFileObject = IrpSp->FileObject; 00291 } 00292 00293 // 00294 // Handle the non-cached read first. 00295 // 00296 00297 if (NonCachedIo) { 00298 00299 // 00300 // If we have an unaligned transfer then post this request if 00301 // we can't wait. Unaligned means that the starting offset 00302 // is not on a sector boundary or the read is not integral 00303 // sectors. 00304 // 00305 00306 ReadByteCount = SectorAlign( Vcb, ByteCount ); 00307 00308 if (SectorOffset( Vcb, StartingOffset ) || 00309 (ReadByteCount > OriginalByteCount)) { 00310 00311 if (!Wait) { 00312 00313 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 00314 } 00315 00316 // 00317 // Make sure we don't overwrite the buffer. 00318 // 00319 00320 ReadByteCount = ByteCount; 00321 } 00322 00323 // 00324 // Initialize the IoContext for the read. 00325 // If there is a context pointer, we need to make sure it was 00326 // allocated and not a stale stack pointer. 00327 // 00328 00329 if (IrpContext->IoContext == NULL || 00330 !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) { 00331 00332 // 00333 // If we can wait, use the context on the stack. Otherwise 00334 // we need to allocate one. 00335 // 00336 00337 if (Wait) { 00338 00339 IrpContext->IoContext = &LocalIoContext; 00340 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO ); 00341 00342 } else { 00343 00344 IrpContext->IoContext = UdfAllocateIoContext(); 00345 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO ); 00346 } 00347 } 00348 00349 RtlZeroMemory( IrpContext->IoContext, sizeof( UDF_IO_CONTEXT )); 00350 00351 // 00352 // Store whether we allocated this context structure in the structure 00353 // itself. 00354 // 00355 00356 IrpContext->IoContext->AllocatedContext = 00357 BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO ); 00358 00359 if (Wait) { 00360 00361 KeInitializeEvent( &IrpContext->IoContext->SyncEvent, 00362 NotificationEvent, 00363 FALSE ); 00364 00365 } else { 00366 00367 IrpContext->IoContext->ResourceThreadId = ExGetCurrentResourceThread(); 00368 IrpContext->IoContext->Resource = Fcb->Resource; 00369 IrpContext->IoContext->RequestedByteCount = ByteCount; 00370 } 00371 00372 Irp->IoStatus.Information = ReadByteCount; 00373 00374 // 00375 // Call the NonCacheIo routine to perform the actual read. 00376 // 00377 00378 Status = UdfNonCachedRead( IrpContext, Fcb, StartingOffset, ReadByteCount ); 00379 00380 // 00381 // Don't complete this request now if STATUS_PENDING was returned. 00382 // 00383 00384 if (Status == STATUS_PENDING) { 00385 00386 Irp = NULL; 00387 ReleaseFile = FALSE; 00388 00389 // 00390 // Test is we should zero part of the buffer or update the 00391 // synchronous file position. 00392 // 00393 00394 } else { 00395 00396 // 00397 // Convert any unknown error code to IO_ERROR. 00398 // 00399 00400 if (!NT_SUCCESS( Status )) { 00401 00402 // 00403 // Set the information field to zero. 00404 // 00405 00406 Irp->IoStatus.Information = 0; 00407 00408 // 00409 // Raise if this is a user induced error. 00410 // 00411 00412 if (IoIsErrorUserInduced( Status )) { 00413 00414 UdfRaiseStatus( IrpContext, Status ); 00415 } 00416 00417 Status = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR ); 00418 00419 // 00420 // Check if there is any portion of the user's buffer to zero. 00421 // 00422 00423 } else if (ReadByteCount != ByteCount) { 00424 00425 UdfMapUserBuffer( IrpContext, &UserBuffer ); 00426 00427 SafeZeroMemory( IrpContext, 00428 Add2Ptr( UserBuffer, 00429 ByteCount, 00430 PVOID ), 00431 ReadByteCount - ByteCount ); 00432 00433 Irp->IoStatus.Information = ByteCount; 00434 } 00435 00436 // 00437 // Update the file position if this is a synchronous request. 00438 // 00439 00440 if (SynchronousIo && !PagingIo && NT_SUCCESS( Status )) { 00441 00442 IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange; 00443 } 00444 } 00445 00446 try_leave( NOTHING ); 00447 } 00448 00449 // 00450 // Handle the cached case. Start by initializing the private 00451 // cache map. 00452 // 00453 00454 if (MappingFileObject->PrivateCacheMap == NULL) { 00455 00456 // 00457 // The metadata Fcb stream was fired up before any data read. We should never 00458 // see it here. 00459 // 00460 00461 ASSERT( MappingFileObject != Vcb->MetadataFcb->FileObject ); 00462 00463 // 00464 // Now initialize the cache map. 00465 // 00466 00467 CcInitializeCacheMap( IrpSp->FileObject, 00468 (PCC_FILE_SIZES) &Fcb->AllocationSize, 00469 FALSE, 00470 &UdfData.CacheManagerCallbacks, 00471 Fcb ); 00472 00473 CcSetReadAheadGranularity( IrpSp->FileObject, READ_AHEAD_GRANULARITY ); 00474 } 00475 00476 // 00477 // Read from the cache if this is not an Mdl read. 00478 // 00479 00480 if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) { 00481 00482 // 00483 // If we are in the Fsp now because we had to wait earlier, 00484 // we must map the user buffer, otherwise we can use the 00485 // user's buffer directly. 00486 // 00487 00488 UdfMapUserBuffer( IrpContext, &SystemBuffer); 00489 00490 // 00491 // Now try to do the copy. 00492 // 00493 00494 if (!CcCopyRead( MappingFileObject, 00495 (PLARGE_INTEGER) &StartingOffset, 00496 ByteCount, 00497 Wait, 00498 SystemBuffer, 00499 &Irp->IoStatus )) { 00500 00501 try_leave( Status = STATUS_CANT_WAIT ); 00502 } 00503 00504 // 00505 // If the call didn't succeed, raise the error status 00506 // 00507 00508 if (!NT_SUCCESS( Irp->IoStatus.Status )) { 00509 00510 UdfNormalizeAndRaiseStatus( IrpContext, Irp->IoStatus.Status ); 00511 } 00512 00513 Status = Irp->IoStatus.Status; 00514 00515 // 00516 // Otherwise perform the MdlRead operation. 00517 // 00518 00519 } else { 00520 00521 CcMdlRead( MappingFileObject, 00522 (PLARGE_INTEGER) &StartingOffset, 00523 ByteCount, 00524 &Irp->MdlAddress, 00525 &Irp->IoStatus ); 00526 00527 Status = Irp->IoStatus.Status; 00528 } 00529 00530 // 00531 // Update the current file position in the user file object. 00532 // 00533 00534 if (SynchronousIo && !PagingIo && NT_SUCCESS( Status )) { 00535 00536 IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange; 00537 } 00538 00539 } finally { 00540 00541 DebugUnwind( "UdfCommonRead" ); 00542 00543 // 00544 // Release the Fcb. 00545 // 00546 00547 if (ReleaseFile) { 00548 00549 UdfReleaseFile( IrpContext, Fcb ); 00550 } 00551 } 00552 00553 // 00554 // Post the request if we got CANT_WAIT. 00555 // 00556 00557 if (Status == STATUS_CANT_WAIT) { 00558 00559 Status = UdfFsdPostRequest( IrpContext, Irp ); 00560 00561 // 00562 // Otherwise complete the request. 00563 // 00564 00565 } else { 00566 00567 UdfCompleteRequest( IrpContext, Irp, Status ); 00568 } 00569 00570 return Status; 00571 }


Generated on Sat May 15 19:45:27 2004 for test by doxygen 1.3.7