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

deviosup.c File Reference

#include "UdfProcs.h"

Go to the source code of this file.

Classes

struct  _IO_RUN

Defines

#define BugCheckFileId   (UDFS_BUG_CHECK_DEVIOSUP)
#define Dbg   (UDFS_DEBUG_LEVEL_DEVIOSUP)
#define MAX_PARALLEL_IOS   5

Typedefs

typedef _IO_RUN IO_RUN
typedef IO_RUNPIO_RUN

Functions

BOOLEAN UdfPrepareBuffers (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PFCB Fcb, IN PVOID UserBuffer, IN ULONG UserBufferOffset, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN PIO_RUN IoRuns, IN PULONG RunCount, IN PULONG ThisByteCount, OUT PBOOLEAN SparseRuns)
BOOLEAN UdfFinishBuffers (IN PIRP_CONTEXT IrpContext, IN PIO_RUN IoRuns, IN ULONG RunCount, IN BOOLEAN FinalCleanup)
VOID UdfMultipleAsync (IN PIRP_CONTEXT IrpContext, IN ULONG RunCount, IN PIO_RUN IoRuns)
VOID UdfSingleAsync (IN PIRP_CONTEXT IrpContext, IN LONGLONG ByteOffset, IN ULONG ByteCount)
VOID UdfWaitSync (IN PIRP_CONTEXT IrpContext)
NTSTATUS UdfMultiSyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS UdfMultiAsyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS UdfSingleSyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS UdfSingleAsyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS UdfNonCachedRead (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN LONGLONG StartingOffset, IN ULONG ByteCount)
NTSTATUS UdfCreateUserMdl (IN PIRP_CONTEXT IrpContext, IN ULONG BufferLength, IN BOOLEAN RaiseOnError)
NTSTATUS UdfPerformDevIoCtrl (IN PIRP_CONTEXT IrpContext, IN ULONG IoControlCode, IN PDEVICE_OBJECT Device, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL)
NTSTATUS UdfReadSectors (IN PIRP_CONTEXT IrpContext, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN BOOLEAN ReturnError, IN OUT PVOID Buffer, IN PDEVICE_OBJECT TargetDeviceObject)
BOOLEAN UdfPrepareBuffers (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PFCB Fcb, IN PVOID UserBuffer, IN ULONG UserBufferOffset, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN PIO_RUN IoRuns, IN PULONG RunCount, IN PULONG ThisByteCount, IN PBOOLEAN SparseRuns)


Define Documentation

#define BugCheckFileId   (UDFS_BUG_CHECK_DEVIOSUP)
 

Definition at line 27 of file deviosup.c.

#define Dbg   (UDFS_DEBUG_LEVEL_DEVIOSUP)
 

Definition at line 33 of file deviosup.c.

#define MAX_PARALLEL_IOS   5
 

Definition at line 107 of file deviosup.c.

Referenced by UdfNonCachedRead(), and UdfPrepareBuffers().


Typedef Documentation

typedef struct _IO_RUN IO_RUN
 

typedef IO_RUN* PIO_RUN
 

Definition at line 105 of file deviosup.c.

Referenced by UdfFinishBuffers(), and UdfPrepareBuffers().


Function Documentation

NTSTATUS UdfCreateUserMdl IN PIRP_CONTEXT  IrpContext,
IN ULONG  BufferLength,
IN BOOLEAN  RaiseOnError
 

Definition at line 474 of file deviosup.c.

References ASSERT, ASSERT_IRP, ASSERT_IRP_CONTEXT, EXCEPTION_EXECUTE_HANDLER, FALSE, FsRtlIsNtstatusExpected(), IoAllocateMdl(), IoFreeMdl(), IoWriteAccess, MmProbeAndLockPages(), NTSTATUS(), NULL, PAGED_CODE, Status, and UdfRaiseStatus().

Referenced by UdfNonCachedRead().

00482 : 00483 00484 This routine locks the specified buffer for read access (we only write into 00485 the buffer). The file system requires this routine since it does not 00486 ask the I/O system to lock its buffers for direct I/O. This routine 00487 may only be called from the Fsd while still in the user context. 00488 00489 This routine is only called if there is not already an Mdl. 00490 00491 Arguments: 00492 00493 BufferLength - Length of user buffer. 00494 00495 RaiseOnError - Indicates if our caller wants this routine to raise on 00496 an error condition. 00497 00498 Return Value: 00499 00500 NTSTATUS - Status from this routine. Error status only returned if 00501 RaiseOnError is FALSE. 00502 00503 --*/ 00504 00505 { 00506 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; 00507 PMDL Mdl; 00508 00509 PAGED_CODE(); 00510 00511 ASSERT_IRP_CONTEXT( IrpContext ); 00512 ASSERT_IRP( IrpContext->Irp ); 00513 ASSERT( IrpContext->Irp->MdlAddress == NULL ); 00514 00515 // 00516 // Allocate the Mdl, and Raise if we fail. 00517 // 00518 00519 Mdl = IoAllocateMdl( IrpContext->Irp->UserBuffer, 00520 BufferLength, 00521 FALSE, 00522 FALSE, 00523 IrpContext->Irp ); 00524 00525 if (Mdl != NULL) { 00526 00527 // 00528 // Now probe the buffer described by the Irp. If we get an exception, 00529 // deallocate the Mdl and return the appropriate "expected" status. 00530 // 00531 00532 try { 00533 00534 MmProbeAndLockPages( Mdl, IrpContext->Irp->RequestorMode, IoWriteAccess ); 00535 00536 Status = STATUS_SUCCESS; 00537 00538 } except(EXCEPTION_EXECUTE_HANDLER) { 00539 00540 Status = GetExceptionCode(); 00541 00542 IoFreeMdl( Mdl ); 00543 IrpContext->Irp->MdlAddress = NULL; 00544 00545 if (!FsRtlIsNtstatusExpected( Status )) { 00546 00547 Status = STATUS_INVALID_USER_BUFFER; 00548 } 00549 } 00550 } 00551 00552 // 00553 // Check if we are to raise or return 00554 // 00555 00556 if (Status != STATUS_SUCCESS) { 00557 00558 if (RaiseOnError) { 00559 00560 UdfRaiseStatus( IrpContext, Status ); 00561 } 00562 } 00563 00564 // 00565 // Return the status code. 00566 // 00567 00568 return Status; 00569 }

BOOLEAN UdfFinishBuffers IN PIRP_CONTEXT  IrpContext,
IN PIO_RUN  IoRuns,
IN ULONG  RunCount,
IN BOOLEAN  FinalCleanup
 

Definition at line 1280 of file deviosup.c.

References Add2Ptr, FALSE, IoFreeIrp(), IoFreeMdl(), _IRP::MdlAddress, NULL, PAGED_CODE, PIO_RUN, _IO_RUN::SavedIrp, _IO_RUN::TransferBuffer, _IO_RUN::TransferBufferOffset, _IO_RUN::TransferByteCount, _IO_RUN::TransferMdl, TRUE, UdfFreePool(), and _IO_RUN::UserBuffer.

Referenced by UdfNonCachedRead().

01289 : 01290 01291 This routine is called to perform any data transferred required for 01292 unaligned Io or to perform the final cleanup of the IoRuns array. 01293 01294 In all cases this is where we will deallocate any buffer and mdl 01295 allocated to perform the unaligned transfer. If this is not the 01296 final cleanup then we also transfer the bytes to the user buffer 01297 and flush the hardware cache. 01298 01299 We walk backwards through the run array because we may be shifting data 01300 in the user's buffer. Typical case is where we allocated a buffer for 01301 the first part of a read and then used the user's buffer for the 01302 next section (but stored it at the beginning of the buffer. 01303 01304 Arguments: 01305 01306 IoRuns - Pointer to the IoRuns array. 01307 01308 RunCount - Number of entries in the IoRuns array filled here. 01309 01310 FinalCleanup - Indicates if we should be deallocating temporary buffers 01311 (TRUE) or transferring bytes for a unaligned transfers and 01312 deallocating the buffers (FALSE). Flush the system cache if 01313 transferring data. 01314 01315 Return Value: 01316 01317 BOOLEAN - TRUE if this request needs the Io buffers to be flushed, FALSE otherwise. 01318 01319 --*/ 01320 01321 { 01322 BOOLEAN FlushIoBuffers = FALSE; 01323 01324 ULONG RemainingEntries = RunCount; 01325 PIO_RUN ThisIoRun = &IoRuns[RunCount - 1]; 01326 01327 PAGED_CODE(); 01328 01329 // 01330 // Walk through each entry in the IoRun array. 01331 // 01332 01333 while (RemainingEntries != 0) { 01334 01335 // 01336 // We only need to deal with the case of an unaligned transfer. 01337 // 01338 01339 if (ThisIoRun->TransferByteCount != 0) { 01340 01341 // 01342 // If not the final cleanup then transfer the data to the 01343 // user's buffer and remember that we will need to flush 01344 // the user's buffer to memory. 01345 // 01346 01347 if (!FinalCleanup) { 01348 01349 // 01350 // If we are shifting in the user's buffer then use 01351 // MoveMemory. 01352 // 01353 01354 if (ThisIoRun->TransferMdl == IrpContext->Irp->MdlAddress) { 01355 01356 RtlMoveMemory( ThisIoRun->UserBuffer, 01357 Add2Ptr( ThisIoRun->TransferBuffer, 01358 ThisIoRun->TransferBufferOffset, 01359 PVOID ), 01360 ThisIoRun->TransferByteCount ); 01361 01362 } else { 01363 01364 RtlCopyMemory( ThisIoRun->UserBuffer, 01365 Add2Ptr( ThisIoRun->TransferBuffer, 01366 ThisIoRun->TransferBufferOffset, 01367 PVOID ), 01368 ThisIoRun->TransferByteCount ); 01369 } 01370 01371 FlushIoBuffers = TRUE; 01372 } 01373 01374 // 01375 // Free any Mdl we may have allocated. If the Mdl isn't 01376 // present then we must have failed during the allocation 01377 // phase. 01378 // 01379 01380 if (ThisIoRun->TransferMdl != IrpContext->Irp->MdlAddress) { 01381 01382 if (ThisIoRun->TransferMdl != NULL) { 01383 01384 IoFreeMdl( ThisIoRun->TransferMdl ); 01385 } 01386 01387 // 01388 // Now free any buffer we may have allocated. If the Mdl 01389 // doesn't match the original Mdl then free the buffer. 01390 // 01391 01392 if (ThisIoRun->TransferBuffer != NULL) { 01393 01394 UdfFreePool( &ThisIoRun->TransferBuffer ); 01395 } 01396 } 01397 } 01398 01399 // 01400 // Now handle the case where we failed in the process 01401 // of allocating associated Irps and Mdls. 01402 // 01403 01404 if (ThisIoRun->SavedIrp != NULL) { 01405 01406 if (ThisIoRun->SavedIrp->MdlAddress != NULL) { 01407 01408 IoFreeMdl( ThisIoRun->SavedIrp->MdlAddress ); 01409 } 01410 01411 IoFreeIrp( ThisIoRun->SavedIrp ); 01412 } 01413 01414 // 01415 // Move to the previous IoRun entry. 01416 // 01417 01418 ThisIoRun -= 1; 01419 RemainingEntries -= 1; 01420 } 01421 01422 // 01423 // If we copied any data then flush the Io buffers. 01424 // 01425 01426 return FlushIoBuffers; 01427 }

NTSTATUS UdfMultiAsyncCompletionRoutine IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context
 

Definition at line 1863 of file deviosup.c.

References ExReleaseResourceForThread, IoFreeIrp(), IoFreeMdl(), IoGetCurrentIrpStackLocation, IoMarkIrpPending, _IRP::IoStatus, Irp, _UDF_IO_CONTEXT::IrpCount, _UDF_IO_CONTEXT::MasterIrp, _IRP::MdlAddress, NT_SUCCESS, _UDF_IO_CONTEXT::RequestedByteCount, _UDF_IO_CONTEXT::Resource, _UDF_IO_CONTEXT::ResourceThreadId, _UDF_IO_CONTEXT::Status, and UdfFreeIoContext.

Referenced by UdfMultipleAsync().

01871 : 01872 01873 This is the completion routine for all asynchronous reads 01874 started via UdfMultipleAsync. 01875 01876 The completion routine has has the following responsibilities: 01877 01878 If the individual request was completed with an error, then 01879 this completion routine must see if this is the first error 01880 and remember the error status in the Context. 01881 01882 Arguments: 01883 01884 DeviceObject - Pointer to the file system device object. 01885 01886 Irp - Pointer to the associated Irp which is being completed. (This 01887 Irp will no longer be accessible after this routine returns.) 01888 01889 Context - The context parameter which was specified for all of 01890 the multiple asynch I/O requests for this MasterIrp. 01891 01892 Return Value: 01893 01894 Currently always returns STATUS_SUCCESS. 01895 01896 --*/ 01897 01898 { 01899 PUDF_IO_CONTEXT IoContext = Context; 01900 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 01901 01902 // 01903 // If we got an error (or verify required), remember it in the Irp 01904 // 01905 01906 if (!NT_SUCCESS( Irp->IoStatus.Status )) { 01907 01908 InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status ); 01909 } 01910 01911 // 01912 // Decrement IrpCount and see if it goes to zero. 01913 // 01914 01915 if (InterlockedDecrement( &IoContext->IrpCount ) == 0) { 01916 01917 // 01918 // Mark the master Irp pending 01919 // 01920 01921 IoMarkIrpPending( IoContext->MasterIrp ); 01922 01923 // 01924 // Update the Master Irp with any error status from the associated Irps. 01925 // 01926 01927 IoContext->MasterIrp->IoStatus.Status = IoContext->Status; 01928 01929 // 01930 // Update the information field with the correct value. 01931 // 01932 01933 IoContext->MasterIrp->IoStatus.Information = 0; 01934 01935 if (NT_SUCCESS( IoContext->MasterIrp->IoStatus.Status )) { 01936 01937 IoContext->MasterIrp->IoStatus.Information = IoContext->RequestedByteCount; 01938 } 01939 01940 // 01941 // Now release the resource 01942 // 01943 01944 ExReleaseResourceForThread( IoContext->Resource, 01945 IoContext->ResourceThreadId ); 01946 01947 // 01948 // and finally, free the context record. 01949 // 01950 01951 UdfFreeIoContext( IoContext ); 01952 01953 // 01954 // Return success in this case. 01955 // 01956 01957 return STATUS_SUCCESS; 01958 01959 } else { 01960 01961 // 01962 // We need to cleanup the associated Irp and its Mdl. 01963 // 01964 01965 IoFreeMdl( Irp->MdlAddress ); 01966 IoFreeIrp( Irp ); 01967 01968 return STATUS_MORE_PROCESSING_REQUIRED; 01969 } 01970 01971 UNREFERENCED_PARAMETER( DeviceObject ); 01972 }

VOID UdfMultipleAsync IN PIRP_CONTEXT  IrpContext,
IN ULONG  RunCount,
IN PIO_RUN  IoRuns
 

Definition at line 1435 of file deviosup.c.

References _IRP::AssociatedIrp, FALSE, FlagOn, IoAllocateMdl(), IoBuildPartialMdl(), IoCallDriver, IoGetCurrentIrpStackLocation, IoGetNextIrpStackLocation, IoMakeAssociatedIrp(), IoSetCompletionRoutine, IoSetNextIrpStackLocation, Irp, IRP_CONTEXT_FLAG_WAIT, IRP_MJ_READ, _IO_STACK_LOCATION::MajorFunction, NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PIO_COMPLETION_ROUTINE, TRUE, UdfMultiAsyncCompletionRoutine(), UdfMultiSyncCompletionRoutine(), UdfRaiseStatus(), and VOID().

Referenced by UdfNonCachedRead().

01443 : 01444 01445 This routine first does the initial setup required of a Master IRP that is 01446 going to be completed using associated IRPs. This routine should not 01447 be used if only one async request is needed, instead the single read 01448 async routines should be called. 01449 01450 A context parameter is initialized, to serve as a communications area 01451 between here and the common completion routine. 01452 01453 Next this routine reads or writes one or more contiguous sectors from 01454 a device asynchronously, and is used if there are multiple reads for a 01455 master IRP. A completion routine is used to synchronize with the 01456 completion of all of the I/O requests started by calls to this routine. 01457 01458 Also, prior to calling this routine the caller must initialize the 01459 IoStatus field in the Context, with the correct success status and byte 01460 count which are expected if all of the parallel transfers complete 01461 successfully. After return this status will be unchanged if all requests 01462 were, in fact, successful. However, if one or more errors occur, the 01463 IoStatus will be modified to reflect the error status and byte count 01464 from the first run (by Vbo) which encountered an error. I/O status 01465 from all subsequent runs will not be indicated. 01466 01467 Arguments: 01468 01469 RunCount - Supplies the number of multiple async requests 01470 that will be issued against the master irp. 01471 01472 IoRuns - Supplies an array containing the Offset and ByteCount for the 01473 separate requests. 01474 01475 Return Value: 01476 01477 None. 01478 01479 --*/ 01480 01481 { 01482 PIO_COMPLETION_ROUTINE CompletionRoutine; 01483 PIO_STACK_LOCATION IrpSp; 01484 PMDL Mdl; 01485 PIRP Irp; 01486 PIRP MasterIrp; 01487 ULONG UnwindRunCount; 01488 01489 PAGED_CODE(); 01490 01491 // 01492 // Set up things according to whether this is truely async. 01493 // 01494 01495 CompletionRoutine = UdfMultiSyncCompletionRoutine; 01496 01497 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 01498 01499 CompletionRoutine = UdfMultiAsyncCompletionRoutine; 01500 } 01501 01502 // 01503 // Initialize some local variables. 01504 // 01505 01506 MasterIrp = IrpContext->Irp; 01507 01508 // 01509 // Itterate through the runs, doing everything that can fail. 01510 // We let the cleanup in CdFinishBuffers clean up on error. 01511 // 01512 01513 for (UnwindRunCount = 0; 01514 UnwindRunCount < RunCount; 01515 UnwindRunCount += 1) { 01516 01517 // 01518 // Create an associated IRP, making sure there is one stack entry for 01519 // us, as well. 01520 // 01521 01522 IoRuns[UnwindRunCount].SavedIrp = 01523 Irp = IoMakeAssociatedIrp( MasterIrp, (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1) ); 01524 01525 if (Irp == NULL) { 01526 01527 IrpContext->Irp->IoStatus.Information = 0; 01528 UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES ); 01529 } 01530 01531 // 01532 // Allocate and build a partial Mdl for the request. 01533 // 01534 01535 Mdl = IoAllocateMdl( IoRuns[UnwindRunCount].TransferVirtualAddress, 01536 IoRuns[UnwindRunCount].DiskByteCount, 01537 FALSE, 01538 FALSE, 01539 Irp ); 01540 01541 if (Mdl == NULL) { 01542 01543 IrpContext->Irp->IoStatus.Information = 0; 01544 UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES ); 01545 } 01546 01547 IoBuildPartialMdl( IoRuns[UnwindRunCount].TransferMdl, 01548 Mdl, 01549 IoRuns[UnwindRunCount].TransferVirtualAddress, 01550 IoRuns[UnwindRunCount].DiskByteCount ); 01551 01552 // 01553 // Get the first IRP stack location in the associated Irp 01554 // 01555 01556 IoSetNextIrpStackLocation( Irp ); 01557 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 01558 01559 // 01560 // Setup the Stack location to describe our read. 01561 // 01562 01563 IrpSp->MajorFunction = IRP_MJ_READ; 01564 IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount; 01565 IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset; 01566 01567 // 01568 // Set up the completion routine address in our stack frame. 01569 // 01570 01571 IoSetCompletionRoutine( Irp, 01572 CompletionRoutine, 01573 IrpContext->IoContext, 01574 TRUE, 01575 TRUE, 01576 TRUE ); 01577 01578 // 01579 // Setup the next IRP stack location in the associated Irp for the disk 01580 // driver beneath us. 01581 // 01582 01583 IrpSp = IoGetNextIrpStackLocation( Irp ); 01584 01585 // 01586 // Setup the Stack location to do a read from the disk driver. 01587 // 01588 01589 IrpSp->MajorFunction = IRP_MJ_READ; 01590 IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount; 01591 IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset; 01592 } 01593 01594 // 01595 // We only need to set the associated IRP count in the master irp to 01596 // make it a master IRP. But we set the count to one more than our 01597 // caller requested, because we do not want the I/O system to complete 01598 // the I/O. We also set our own count. 01599 // 01600 01601 IrpContext->IoContext->IrpCount = RunCount; 01602 IrpContext->IoContext->MasterIrp = MasterIrp; 01603 01604 // 01605 // We set the count in the master Irp to 1 since typically we 01606 // will clean up the associated irps ourselves. Setting this to one 01607 // means completing the last associated Irp with SUCCESS (in the async 01608 // case) will complete the master irp. 01609 // 01610 01611 MasterIrp->AssociatedIrp.IrpCount = 1; 01612 01613 // 01614 // Now that all the dangerous work is done, issue the Io requests 01615 // 01616 01617 for (UnwindRunCount = 0; 01618 UnwindRunCount < RunCount; 01619 UnwindRunCount++) { 01620 01621 Irp = IoRuns[UnwindRunCount].SavedIrp; 01622 IoRuns[UnwindRunCount].SavedIrp = NULL; 01623 01624 // 01625 // If IoCallDriver returns an error, it has completed the Irp 01626 // and the error will be caught by our completion routines 01627 // and dealt with as a normal IO error. 01628 // 01629 01630 (VOID) IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp ); 01631 } 01632 01633 return; 01634 }

NTSTATUS UdfMultiSyncCompletionRoutine IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context
 

Definition at line 1779 of file deviosup.c.

References FALSE, IoFreeIrp(), IoFreeMdl(), _IRP::IoStatus, Irp, _UDF_IO_CONTEXT::IrpCount, KeSetEvent(), _UDF_IO_CONTEXT::MasterIrp, _IRP::MdlAddress, NT_SUCCESS, PUDF_IO_CONTEXT, _UDF_IO_CONTEXT::Status, and _UDF_IO_CONTEXT::SyncEvent.

Referenced by UdfMultipleAsync().

01787 : 01788 01789 This is the completion routine for all synchronous reads 01790 started via UdfMultipleAsync. 01791 01792 The completion routine has has the following responsibilities: 01793 01794 If the individual request was completed with an error, then 01795 this completion routine must see if this is the first error 01796 and remember the error status in the Context. 01797 01798 If the IrpCount goes to 1, then it sets the event in the Context 01799 parameter to signal the caller that all of the asynch requests 01800 are done. 01801 01802 Arguments: 01803 01804 DeviceObject - Pointer to the file system device object. 01805 01806 Irp - Pointer to the associated Irp which is being completed. (This 01807 Irp will no longer be accessible after this routine returns.) 01808 01809 Context - The context parameter which was specified for all of 01810 the multiple asynch I/O requests for this MasterIrp. 01811 01812 Return Value: 01813 01814 The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can 01815 immediately complete the Master Irp without being in a race condition 01816 with the IoCompleteRequest thread trying to decrement the IrpCount in 01817 the Master Irp. 01818 01819 --*/ 01820 01821 { 01822 PUDF_IO_CONTEXT IoContext = Context; 01823 01824 // 01825 // If we got an error (or verify required), remember it in the Irp 01826 // 01827 01828 if (!NT_SUCCESS( Irp->IoStatus.Status )) { 01829 01830 InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status ); 01831 IoContext->MasterIrp->IoStatus.Information = 0; 01832 } 01833 01834 // 01835 // We must do this here since IoCompleteRequest won't get a chance 01836 // on this associated Irp. 01837 // 01838 01839 IoFreeMdl( Irp->MdlAddress ); 01840 IoFreeIrp( Irp ); 01841 01842 if (InterlockedDecrement( &IoContext->IrpCount ) == 0) { 01843 01844 // 01845 // Update the Master Irp with any error status from the associated Irps. 01846 // 01847 01848 IoContext->MasterIrp->IoStatus.Status = IoContext->Status; 01849 KeSetEvent( &IoContext->SyncEvent, 0, FALSE ); 01850 } 01851 01852 UNREFERENCED_PARAMETER( DeviceObject ); 01853 01854 return STATUS_MORE_PROCESSING_REQUIRED; 01855 }

NTSTATUS UdfNonCachedRead IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb,
IN LONGLONG  StartingOffset,
IN ULONG  ByteCount
 

Definition at line 201 of file deviosup.c.

References Add2Ptr, ASSERT, ClearFlag, DebugUnwind, FALSE, FCB_STATE_EMBEDDED_DATA, FCB_STATE_VMCB_MAPPING, FlagOn, IRP_CONTEXT_FLAG_ALLOC_IO, IRP_CONTEXT_FLAG_WAIT, KeFlushIoBuffers(), MAX_PARALLEL_IOS, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, TRUE, try_leave, UdfCreateUserMdl(), UdfFinishBuffers(), UdfMapUserBuffer, UdfMultipleAsync(), UdfPrepareBuffers(), UdfRaiseStatus(), UdfSingleAsync(), and UdfWaitSync().

Referenced by UdfCommonRead().

00210 : 00211 00212 This routine performs the non-cached reads of sectors. This is done by 00213 performing the following in a loop. 00214 00215 Fill in the IoRuns array for the next block of Io. 00216 Send the Io to the device. 00217 Perform any cleanup on the Io runs array. 00218 00219 We will not do async Io to any request that generates non-aligned Io. 00220 Also we will not perform async Io if it will exceed the size of our 00221 IoRuns array. These should be the unusual cases but we will raise 00222 or return CANT_WAIT in this routine if we detect this case. 00223 00224 Arguments: 00225 00226 Fcb - Fcb representing the file to read. 00227 00228 StartingOffset - Logical offset in the file to read from. 00229 00230 ByteCount - Number of bytes to read. 00231 00232 Return Value: 00233 00234 NTSTATUS - Status indicating the result of the operation. 00235 00236 --*/ 00237 00238 { 00239 NTSTATUS Status = STATUS_SUCCESS; 00240 00241 IO_RUN IoRuns[MAX_PARALLEL_IOS]; 00242 ULONG RunCount = 0; 00243 ULONG CleanupRunCount = 0; 00244 00245 PVOID UserBuffer; 00246 ULONG UserBufferOffset = 0; 00247 LONGLONG CurrentOffset = StartingOffset; 00248 ULONG RemainingByteCount = ByteCount; 00249 ULONG ThisByteCount; 00250 00251 BOOLEAN Unaligned; 00252 BOOLEAN SparseRuns; 00253 BOOLEAN FlushIoBuffers = FALSE; 00254 BOOLEAN FirstPass = TRUE; 00255 00256 PAGED_CODE(); 00257 00258 // 00259 // We want to make sure the user's buffer is locked in all cases. 00260 // 00261 00262 if (IrpContext->Irp->MdlAddress == NULL) { 00263 00264 UdfCreateUserMdl( IrpContext, ByteCount, TRUE ); 00265 } 00266 00267 // 00268 // Use a try-finally to perform the final cleanup. 00269 // 00270 00271 try { 00272 00273 UdfMapUserBuffer( IrpContext, &UserBuffer); 00274 00275 // 00276 // Loop while there are more bytes to transfer. 00277 // 00278 00279 do { 00280 00281 // 00282 // Call prepare buffers to set up the next entries 00283 // in the IoRuns array. Remember if there are any 00284 // unaligned entries. 00285 // 00286 00287 RtlZeroMemory( IoRuns, sizeof( IoRuns )); 00288 00289 Unaligned = UdfPrepareBuffers( IrpContext, 00290 IrpContext->Irp, 00291 Fcb, 00292 UserBuffer, 00293 UserBufferOffset, 00294 CurrentOffset, 00295 RemainingByteCount, 00296 IoRuns, 00297 &CleanupRunCount, 00298 &ThisByteCount, 00299 &SparseRuns ); 00300 00301 00302 RunCount = CleanupRunCount; 00303 00304 // 00305 // Quickly finish if we wound up having no IO to perform. This will 00306 // occur in the presence of unrecorded sectors. 00307 // 00308 00309 ASSERT( !(SparseRuns && FlagOn( Fcb->FcbState, FCB_STATE_VMCB_MAPPING|FCB_STATE_EMBEDDED_DATA ))); 00310 00311 if (RunCount == 0) { 00312 00313 try_leave( Status = IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS ); 00314 } 00315 00316 // 00317 // If this is an async request and there aren't enough entries 00318 // in the Io array then post the request. This routine will 00319 // always raise if we are doing any unaligned Io for an 00320 // async request. 00321 // 00322 00323 if ((ThisByteCount < RemainingByteCount) && 00324 !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 00325 00326 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 00327 } 00328 00329 // 00330 // If the entire Io is contained in a single run then 00331 // we can pass the Io down to the driver. Send the driver down 00332 // and wait on the result if this is synchronous. We cannot 00333 // do this simple form (just chucking the IRP down) if some 00334 // sparse runs were encountered. 00335 // 00336 00337 if ((RunCount == 1) && !Unaligned && !SparseRuns && FirstPass) { 00338 00339 UdfSingleAsync( IrpContext, 00340 IoRuns[0].DiskOffset, 00341 IoRuns[0].DiskByteCount ); 00342 00343 // 00344 // No cleanup needed for the IoRuns array here. 00345 // 00346 00347 CleanupRunCount = 0; 00348 00349 // 00350 // Wait if we are synchronous, otherwise return 00351 // 00352 00353 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 00354 00355 UdfWaitSync( IrpContext ); 00356 00357 Status = IrpContext->Irp->IoStatus.Status; 00358 00359 // 00360 // Our completion routine will free the Io context but 00361 // we do want to return STATUS_PENDING. 00362 // 00363 00364 } else { 00365 00366 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO ); 00367 Status = STATUS_PENDING; 00368 } 00369 00370 try_leave( NOTHING ); 00371 } 00372 00373 // 00374 // Otherwise we will perform multiple Io to read in the data. 00375 // 00376 00377 UdfMultipleAsync( IrpContext, RunCount, IoRuns ); 00378 00379 // 00380 // No cleanup needed on the IoRuns now. 00381 // 00382 00383 CleanupRunCount = 0; 00384 00385 // 00386 // If this is a synchronous request then perform any necessary 00387 // post-processing. 00388 // 00389 00390 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 00391 00392 // 00393 // Wait for the request to complete. 00394 // 00395 00396 UdfWaitSync( IrpContext ); 00397 00398 Status = IrpContext->Irp->IoStatus.Status; 00399 00400 // 00401 // Exit this loop if there is an error. 00402 // 00403 00404 if (!NT_SUCCESS( Status )) { 00405 00406 try_leave( NOTHING ); 00407 } 00408 00409 // 00410 // Perform post read operations on the IoRuns if 00411 // necessary. 00412 // 00413 00414 if (Unaligned && 00415 UdfFinishBuffers( IrpContext, IoRuns, RunCount, FALSE )) { 00416 00417 FlushIoBuffers = TRUE; 00418 } 00419 00420 // 00421 // Exit this loop if there are no more bytes to transfer 00422 // or we have any error. 00423 // 00424 00425 RemainingByteCount -= ThisByteCount; 00426 CurrentOffset += ThisByteCount; 00427 UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID ); 00428 UserBufferOffset += ThisByteCount; 00429 00430 // 00431 // Otherwise this is an asynchronous request. Always return 00432 // STATUS_PENDING. 00433 // 00434 00435 } else { 00436 00437 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO ); 00438 CleanupRunCount = 0; 00439 try_leave( Status = STATUS_PENDING ); 00440 break; 00441 } 00442 00443 FirstPass = FALSE; 00444 } while (RemainingByteCount != 0); 00445 00446 // 00447 // Flush the hardware cache if we performed any copy operations. 00448 // 00449 00450 if (FlushIoBuffers) { 00451 00452 KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE ); 00453 } 00454 00455 } finally { 00456 00457 DebugUnwind( "UdfNonCachedRead" ); 00458 00459 // 00460 // Perform final cleanup on the IoRuns if necessary. 00461 // 00462 00463 if (CleanupRunCount != 0) { 00464 00465 UdfFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE ); 00466 } 00467 } 00468 00469 return Status; 00470 }

NTSTATUS UdfPerformDevIoCtrl IN PIRP_CONTEXT  IrpContext,
IN ULONG  IoControlCode,
IN PDEVICE_OBJECT  Device,
OUT PVOID OutputBuffer  OPTIONAL,
IN ULONG  OutputBufferLength,
IN BOOLEAN  InternalDeviceIoControl,
IN BOOLEAN  OverrideVerify,
OUT PIO_STATUS_BLOCK Iosb  OPTIONAL
 

Definition at line 573 of file deviosup.c.

References Event(), Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, Irp, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NTSTATUS(), NULL, PAGED_CODE, SetFlag, SL_OVERRIDE_VERIFY_VOLUME, Status, and VOID().

Referenced by UdfDetermineVolumeBounding(), UdfMountVolume(), UdfVerifyVcb(), and UdfVerifyVolume().

00586 : 00587 00588 This routine is called to perform DevIoCtrl functions internally within 00589 the filesystem. We take the status from the driver and return it to our 00590 caller. 00591 00592 Arguments: 00593 00594 IoControlCode - Code to send to driver. 00595 00596 Device - This is the device to send the request to. 00597 00598 OutPutBuffer - Pointer to output buffer. 00599 00600 OutputBufferLength - Length of output buffer above. 00601 00602 InternalDeviceIoControl - Indicates if this is an internal or external 00603 Io control code. 00604 00605 OverrideVerify - Indicates if we should tell the driver not to return 00606 STATUS_VERIFY_REQUIRED for mount and verify. 00607 00608 Iosb - If specified, we return the results of the operation here. 00609 00610 Return Value: 00611 00612 NTSTATUS - Status returned by next lower driver. 00613 00614 --*/ 00615 00616 { 00617 NTSTATUS Status; 00618 PIRP Irp; 00619 KEVENT Event; 00620 IO_STATUS_BLOCK LocalIosb; 00621 PIO_STATUS_BLOCK IosbToUse = &LocalIosb; 00622 00623 PAGED_CODE(); 00624 00625 // 00626 // Check if the user gave us an Iosb. 00627 // 00628 00629 if (ARGUMENT_PRESENT( Iosb )) { 00630 00631 IosbToUse = Iosb; 00632 } 00633 00634 IosbToUse->Status = 0; 00635 IosbToUse->Information = 0; 00636 00637 KeInitializeEvent( &Event, NotificationEvent, FALSE ); 00638 00639 Irp = IoBuildDeviceIoControlRequest( IoControlCode, 00640 Device, 00641 NULL, 00642 0, 00643 OutputBuffer, 00644 OutputBufferLength, 00645 InternalDeviceIoControl, 00646 &Event, 00647 IosbToUse ); 00648 00649 if (Irp == NULL) { 00650 00651 return STATUS_INSUFFICIENT_RESOURCES; 00652 } 00653 00654 if (OverrideVerify) { 00655 00656 SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME ); 00657 } 00658 00659 Status = IoCallDriver( Device, Irp ); 00660 00661 // 00662 // We check for device not ready by first checking Status 00663 // and then if status pending was returned, the Iosb status 00664 // value. 00665 // 00666 00667 if (Status == STATUS_PENDING) { 00668 00669 (VOID) KeWaitForSingleObject( &Event, 00670 Executive, 00671 KernelMode, 00672 FALSE, 00673 (PLARGE_INTEGER)NULL ); 00674 00675 Status = IosbToUse->Status; 00676 } 00677 00678 return Status; 00679 00680 UNREFERENCED_PARAMETER( IrpContext ); 00681 }

BOOLEAN UdfPrepareBuffers IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp,
IN PFCB  Fcb,
IN PVOID  UserBuffer,
IN ULONG  UserBufferOffset,
IN LONGLONG  StartingOffset,
IN ULONG  ByteCount,
IN PIO_RUN  IoRuns,
IN PULONG  RunCount,
IN PULONG  ThisByteCount,
IN PBOOLEAN  SparseRuns
 

Definition at line 883 of file deviosup.c.

References Add2Ptr, _IO_RUN::DiskByteCount, _IO_RUN::DiskOffset, FALSE, FlagOn, FsRtlAllocatePoolWithTag, IoAllocateMdl(), Irp, IRP_CONTEXT_FLAG_WAIT, LlSectorTruncate, MAX_PARALLEL_IOS, _IRP::MdlAddress, MmBuildMdlForNonPagedPool(), NULL, PAGE_SIZE, PAGED_CODE, PIO_RUN, SectorAlign, SectorOffset, SectorSize, SectorTruncate, TAG_IO_BUFFER, _IO_RUN::TransferBuffer, _IO_RUN::TransferBufferOffset, _IO_RUN::TransferByteCount, _IO_RUN::TransferMdl, _IO_RUN::TransferVirtualAddress, TRUE, UdfLookupAllocation(), UdfNonPagedPool, UdfRaiseStatus(), _IRP::UserBuffer, and _IO_RUN::UserBuffer.

Referenced by UdfNonCachedRead().

00899 : 00900 00901 This routine is the worker routine which looks up each run of an IO 00902 request and stores an entry for it in the IoRuns array. If the run 00903 begins on an unaligned disk boundary then we will allocate a buffer 00904 and Mdl for the unaligned portion and put it in the IoRuns entry. 00905 00906 This routine will raise CANT_WAIT if an unaligned transfer is encountered 00907 and this request can't wait. 00908 00909 Arguments: 00910 00911 Irp - Originating Irp for this request. 00912 00913 Fcb - This is the Fcb for this data stream. It may be a file, directory, 00914 path table or the volume file. 00915 00916 UserBuffer - Current position in the user's buffer. 00917 00918 UserBufferOffset - Offset from the start of the original user buffer. 00919 00920 StartingOffset - Offset in the stream to begin the read. 00921 00922 ByteCount - Number of bytes to read. We will fill the IoRuns array up 00923 to this point. We will stop early if we exceed the maximum number 00924 of parallel Ios we support. 00925 00926 IoRuns - Pointer to the IoRuns array. The entire array is zeroes when 00927 this routine is called. 00928 00929 RunCount - Number of entries in the IoRuns array filled here. 00930 00931 ThisByteCount - Number of bytes described by the IoRun entries. Will 00932 not exceed the ByteCount passed in. 00933 00934 SparseRuns - Will indicate whether sparse runs were a component of the 00935 range returned. While not part of the IoRuns, this will affect 00936 our ability to do simple IO. 00937 00938 Return Value: 00939 00940 BOOLEAN - TRUE if one of the entries in an unaligned buffer (provided 00941 this is synchronous). FALSE otherwise. 00942 00943 --*/ 00944 00945 { 00946 PVCB Vcb; 00947 00948 BOOLEAN Recorded; 00949 00950 BOOLEAN FoundUnaligned = FALSE; 00951 PIO_RUN ThisIoRun = IoRuns; 00952 00953 // 00954 // Following indicate where we are in the current transfer. Current 00955 // position in the file and number of bytes yet to transfer from 00956 // this position. 00957 // 00958 00959 ULONG RemainingByteCount = ByteCount; 00960 LONGLONG CurrentFileOffset = StartingOffset; 00961 00962 // 00963 // Following indicate the state of the user's buffer. We have 00964 // the destination of the next transfer and its offset in the 00965 // buffer. We also have the next available position in the buffer 00966 // available for a scratch buffer. We will align this up to a sector 00967 // boundary. 00968 // 00969 00970 PVOID CurrentUserBuffer = UserBuffer; 00971 ULONG CurrentUserBufferOffset = UserBufferOffset; 00972 00973 PVOID ScratchUserBuffer = UserBuffer; 00974 ULONG ScratchUserBufferOffset = UserBufferOffset; 00975 00976 // 00977 // The following is the next contiguous bytes on the disk to 00978 // transfer. Read from the allocation package. 00979 // 00980 00981 LONGLONG DiskOffset; 00982 ULONG CurrentByteCount; 00983 00984 PAGED_CODE(); 00985 00986 Vcb = Fcb->Vcb; 00987 00988 // 00989 // Initialize the RunCount, ByteCount and SparseRuns. 00990 // 00991 00992 *RunCount = 0; 00993 *ThisByteCount = 0; 00994 *SparseRuns = FALSE; 00995 00996 // 00997 // Loop while there are more bytes to process or there are 00998 // available entries in the IoRun array. 00999 // 01000 01001 while (TRUE) { 01002 01003 *RunCount += 1; 01004 01005 // 01006 // Initialize the current position in the IoRuns array. 01007 // Find the user's buffer for this portion of the transfer. 01008 // 01009 01010 ThisIoRun->UserBuffer = CurrentUserBuffer; 01011 01012 // 01013 // Find the allocation information for the current offset in the 01014 // stream. 01015 // 01016 01017 Recorded = UdfLookupAllocation( IrpContext, 01018 Fcb, 01019 CurrentFileOffset, 01020 &DiskOffset, 01021 &CurrentByteCount ); 01022 01023 // 01024 // Limit ourselves to the data requested. 01025 // 01026 01027 if (CurrentByteCount > RemainingByteCount) { 01028 01029 CurrentByteCount = RemainingByteCount; 01030 } 01031 01032 // 01033 // Handle the case of unrecorded data first. 01034 // 01035 01036 if (!Recorded) { 01037 01038 // 01039 // Note that we did not consume an entry. 01040 // 01041 01042 *RunCount -= 1; 01043 01044 // 01045 // Immediately zero the user buffer and indicate that we found sparse 01046 // runs to the caller. 01047 // 01048 01049 RtlZeroMemory( CurrentUserBuffer, CurrentByteCount ); 01050 *SparseRuns = TRUE; 01051 01052 // 01053 // Push the scratch buffer pointers forward so that we don't stomp 01054 // on the zeroed buffer. 01055 // 01056 01057 ScratchUserBuffer = Add2Ptr( CurrentUserBuffer, 01058 CurrentByteCount, 01059 PVOID ); 01060 01061 ScratchUserBufferOffset += CurrentByteCount; 01062 01063 // 01064 // Handle the case where this is an unaligned transfer. The 01065 // following must all be true for this to be an aligned transfer. 01066 // 01067 // Disk offset on a 2048 byte boundary (Start of transfer) 01068 // 01069 // Byte count is a multiple of 2048 (Length of transfer) 01070 // 01071 // Current buffer offset is also on a 2048 byte boundary. 01072 // 01073 // If the ByteCount is at least one sector then do the 01074 // unaligned transfer only for the tail. We can use the 01075 // user's buffer for the aligned portion. 01076 // 01077 01078 } else if (SectorOffset( Vcb, DiskOffset ) || 01079 SectorOffset( Vcb, CurrentUserBufferOffset ) || 01080 (SectorOffset( Vcb, CurrentByteCount ) && 01081 CurrentByteCount < SectorSize( Vcb ))) { 01082 01083 // 01084 // If we can't wait then raise. 01085 // 01086 01087 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 01088 01089 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 01090 } 01091 01092 // 01093 // Remember the offset and the number of bytes out of 01094 // the transfer buffer to copy into the user's buffer. 01095 // We will truncate the current read to end on a sector 01096 // boundary. 01097 // 01098 01099 ThisIoRun->TransferBufferOffset = SectorOffset( Vcb, DiskOffset ); 01100 01101 // 01102 // Make sure this transfer ends on a sector boundary. 01103 // 01104 01105 ThisIoRun->DiskOffset = LlSectorTruncate( Vcb, DiskOffset ); 01106 01107 // 01108 // Check if we can use a free portion of the user's buffer. 01109 // If we can copy the bytes to an earlier portion of the 01110 // buffer then read into that location and slide the bytes 01111 // up. 01112 // 01113 // We can use the user's buffer if: 01114 // 01115 // The temporary location in the buffer is before the 01116 // final destination. 01117 // 01118 // There is at least one sector of data to read. 01119 // 01120 01121 if ((ScratchUserBufferOffset + ThisIoRun->TransferBufferOffset < CurrentUserBufferOffset) && 01122 (ThisIoRun->TransferBufferOffset + CurrentByteCount >= SectorSize( Vcb ))) { 01123 01124 ThisIoRun->DiskByteCount = SectorTruncate( Vcb, ThisIoRun->TransferBufferOffset + CurrentByteCount ); 01125 CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset; 01126 ThisIoRun->TransferByteCount = CurrentByteCount; 01127 01128 // 01129 // Point to the user's buffer and Mdl for this transfer. 01130 // 01131 01132 ThisIoRun->TransferBuffer = ScratchUserBuffer; 01133 ThisIoRun->TransferMdl = Irp->MdlAddress; 01134 ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer, 01135 ScratchUserBufferOffset, 01136 PVOID ); 01137 01138 ScratchUserBuffer = Add2Ptr( ScratchUserBuffer, 01139 ThisIoRun->DiskByteCount, 01140 PVOID ); 01141 01142 ScratchUserBufferOffset += ThisIoRun->DiskByteCount; 01143 01144 // 01145 // Otherwise we need to allocate an auxilary buffer for the next sector. 01146 // 01147 01148 } else { 01149 01150 // 01151 // Read up to a page containing the partial data 01152 // 01153 01154 ThisIoRun->DiskByteCount = SectorAlign( Vcb, ThisIoRun->TransferBufferOffset + CurrentByteCount ); 01155 01156 if (ThisIoRun->DiskByteCount > PAGE_SIZE) { 01157 01158 ThisIoRun->DiskByteCount = PAGE_SIZE; 01159 } 01160 01161 if (ThisIoRun->TransferBufferOffset + CurrentByteCount > ThisIoRun->DiskByteCount) { 01162 01163 CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset; 01164 } 01165 01166 ThisIoRun->TransferByteCount = CurrentByteCount; 01167 01168 // 01169 // Allocate a buffer for the non-aligned transfer. 01170 // 01171 01172 ThisIoRun->TransferBuffer = FsRtlAllocatePoolWithTag( UdfNonPagedPool, 01173 PAGE_SIZE, 01174 TAG_IO_BUFFER ); 01175 01176 // 01177 // Allocate and build the Mdl to describe this buffer. 01178 // 01179 01180 ThisIoRun->TransferMdl = IoAllocateMdl( ThisIoRun->TransferBuffer, 01181 PAGE_SIZE, 01182 FALSE, 01183 FALSE, 01184 NULL ); 01185 01186 ThisIoRun->TransferVirtualAddress = ThisIoRun->TransferBuffer; 01187 01188 if (ThisIoRun->TransferMdl == NULL) { 01189 01190 IrpContext->Irp->IoStatus.Information = 0; 01191 UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES ); 01192 } 01193 01194 MmBuildMdlForNonPagedPool( ThisIoRun->TransferMdl ); 01195 } 01196 01197 // 01198 // Remember we found an unaligned transfer. 01199 // 01200 01201 FoundUnaligned = TRUE; 01202 01203 // 01204 // Otherwise we use the buffer and Mdl from the original request. 01205 // 01206 01207 } else { 01208 01209 // 01210 // Truncate the read length to a sector-aligned value. We know 01211 // the length must be at least one sector or we wouldn't be 01212 // here now. 01213 // 01214 01215 CurrentByteCount = SectorTruncate( Vcb, CurrentByteCount ); 01216 01217 // 01218 // Read these sectors from the disk. 01219 // 01220 01221 ThisIoRun->DiskOffset = DiskOffset; 01222 ThisIoRun->DiskByteCount = CurrentByteCount; 01223 01224 // 01225 // Use the user's buffer and Mdl as our transfer buffer 01226 // and Mdl. 01227 // 01228 01229 ThisIoRun->TransferBuffer = CurrentUserBuffer; 01230 ThisIoRun->TransferMdl = Irp->MdlAddress; 01231 ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer, 01232 CurrentUserBufferOffset, 01233 PVOID ); 01234 01235 ScratchUserBuffer = Add2Ptr( CurrentUserBuffer, 01236 CurrentByteCount, 01237 PVOID ); 01238 01239 ScratchUserBufferOffset += CurrentByteCount; 01240 } 01241 01242 // 01243 // Update our position in the transfer and the RunCount and 01244 // ByteCount for the user. 01245 // 01246 01247 RemainingByteCount -= CurrentByteCount; 01248 01249 // 01250 // Break out if no more positions in the IoRuns array or 01251 // we have all of the bytes accounted for. 01252 // 01253 01254 *ThisByteCount += CurrentByteCount; 01255 01256 if ((RemainingByteCount == 0) || (*RunCount == MAX_PARALLEL_IOS)) { 01257 01258 break; 01259 } 01260 01261 // 01262 // Update our pointers for the user's buffer. 01263 // 01264 01265 ThisIoRun = IoRuns + *RunCount; 01266 CurrentUserBuffer = Add2Ptr( CurrentUserBuffer, CurrentByteCount, PVOID ); 01267 CurrentUserBufferOffset += CurrentByteCount; 01268 CurrentFileOffset += CurrentByteCount; 01269 } 01270 01271 return FoundUnaligned; 01272 }

BOOLEAN UdfPrepareBuffers IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp,
IN PFCB  Fcb,
IN PVOID  UserBuffer,
IN ULONG  UserBufferOffset,
IN LONGLONG  StartingOffset,
IN ULONG  ByteCount,
IN PIO_RUN  IoRuns,
IN PULONG  RunCount,
IN PULONG  ThisByteCount,
OUT PBOOLEAN  SparseRuns
 

NTSTATUS UdfReadSectors IN PIRP_CONTEXT  IrpContext,
IN LONGLONG  StartingOffset,
IN ULONG  ByteCount,
IN BOOLEAN  ReturnError,
IN OUT PVOID  Buffer,
IN PDEVICE_OBJECT  TargetDeviceObject
 

Definition at line 685 of file deviosup.c.

References ASSERT, Buffer, BytesFromSectors, Dbg, DebugTrace, Event(), Executive, FALSE, FlagOn, FsRtlLookupLargeMcbEntry(), IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, Irp, IRP_MJ_READ, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), LlSectorsFromBytes, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, SectorSize, SetFlag, SL_OVERRIDE_VERIFY_VOLUME, Status, UdfMethod2TransformByteOffset, UdfNormalizeAndRaiseStatus(), UdfRaiseStatus(), and VCB_STATE_METHOD_2_FIXUP.

Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfLoadSparingTables(), UdfRecognizeVolume(), and UdfUpdateVcbPhase0().

00696 : 00697 00698 This routine is called to transfer sectors from the disk to a 00699 specified buffer. It is used for mount and volume verify operations. 00700 00701 This routine is synchronous, it will not return until the operation 00702 is complete or until the operation fails. 00703 00704 The routine allocates an IRP and then passes this IRP to a lower 00705 level driver. Errors may occur in the allocation of this IRP or 00706 in the operation of the lower driver. 00707 00708 Arguments: 00709 00710 StartingOffset - Logical offset on the disk to start the read. This 00711 must be on a sector boundary, no check is made here. 00712 00713 ByteCount - Number of bytes to read. This is an integral number of 00714 sectors, or otherwise a value we know the driver can handle, 00715 no check is made here to confirm this. 00716 00717 ReturnError - Indicates whether we should return TRUE or FALSE 00718 to indicate an error or raise an error condition. This only applies 00719 to the result of the IO. Any other error may cause a raise. 00720 00721 Buffer - Buffer to transfer the disk data into. 00722 00723 TargetDeviceObject - The device object for the volume to be read. 00724 00725 Return Value: 00726 00727 The final status of the operation. 00728 00729 --*/ 00730 00731 { 00732 PLONGLONG UseStartingOffset; 00733 LONGLONG LocalStartingOffset; 00734 NTSTATUS Status; 00735 KEVENT Event; 00736 PIRP Irp; 00737 00738 PAGED_CODE(); 00739 00740 DebugTrace(( +1, Dbg, 00741 "UdfReadSectors, %x%08x +%x -> %08x from DO %08x\n", 00742 ((PLARGE_INTEGER)&StartingOffset)->HighPart, 00743 ((PLARGE_INTEGER)&StartingOffset)->LowPart, 00744 ByteCount, 00745 Buffer, 00746 TargetDeviceObject )); 00747 00748 // 00749 // For the time being, we assume that we only read sector-at-a-time. 00750 // This simplifies sparing, and is the only way I am aware of this 00751 // code would not be ready for blocksize != sectorsize. It just is 00752 // not worth writing dead (but straightforward) code right now. 00753 // 00754 00755 ASSERT( IrpContext->Vcb == NULL || ByteCount == SectorSize( IrpContext->Vcb )); 00756 00757 // 00758 // If the volume is spared (and at a point where sparing is possible), 00759 // check if a mapping needs to be performed. 00760 // 00761 00762 if (IrpContext->Vcb && 00763 IrpContext->Vcb->Pcb && 00764 IrpContext->Vcb->Pcb->SparingMcb) { 00765 00766 LONGLONG SparingPsn; 00767 00768 if (FsRtlLookupLargeMcbEntry( IrpContext->Vcb->Pcb->SparingMcb, 00769 LlSectorsFromBytes( IrpContext->Vcb, StartingOffset ), 00770 &SparingPsn, 00771 NULL, 00772 NULL, 00773 NULL, 00774 NULL ) && 00775 SparingPsn != -1) { 00776 00777 StartingOffset = BytesFromSectors( IrpContext->Vcb, (ULONG) SparingPsn ); 00778 } 00779 } 00780 00781 // 00782 // Initialize the event. 00783 // 00784 00785 KeInitializeEvent( &Event, NotificationEvent, FALSE ); 00786 00787 // 00788 // Correct the starting offset by the method 2 fixup if neccesary. This also 00789 // assumes sector-at-a-time and sector == block so we don't need to fragment 00790 // the request or check if it spans a packet boundary. 00791 // 00792 // We assume that no fixups are required until a Vcb exists. This is true 00793 // since volume recognition may proceed in the first packet. 00794 // 00795 00796 UseStartingOffset = &StartingOffset; 00797 00798 if (IrpContext->Vcb && 00799 FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) { 00800 00801 LocalStartingOffset = UdfMethod2TransformByteOffset( IrpContext->Vcb, StartingOffset ); 00802 UseStartingOffset = &LocalStartingOffset; 00803 00804 DebugTrace(( 0, Dbg, 00805 "UdfReadSectors, Method2 Fixup to %x%08x\n", 00806 ((PLARGE_INTEGER)UseStartingOffset)->HighPart, 00807 ((PLARGE_INTEGER)UseStartingOffset)->LowPart )); 00808 } 00809 00810 // 00811 // Attempt to allocate the IRP. If unsuccessful, raise 00812 // STATUS_INSUFFICIENT_RESOURCES. 00813 // 00814 00815 Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 00816 TargetDeviceObject, 00817 Buffer, 00818 ByteCount, 00819 (PLARGE_INTEGER) UseStartingOffset, 00820 &Event, 00821 &IrpContext->Irp->IoStatus ); 00822 00823 if (Irp == NULL) { 00824 00825 UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES ); 00826 } 00827 00828 // 00829 // Ignore the change line (verify) for mount and verify requests 00830 // 00831 00832 SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME ); 00833 00834 // 00835 // Send the request down to the driver. If an error occurs return 00836 // it to the caller. 00837 // 00838 00839 Status = IoCallDriver( TargetDeviceObject, Irp ); 00840 00841 // 00842 // If the status was STATUS_PENDING then wait on the event. 00843 // 00844 00845 if (Status == STATUS_PENDING) { 00846 00847 Status = KeWaitForSingleObject( &Event, 00848 Executive, 00849 KernelMode, 00850 FALSE, 00851 NULL ); 00852 00853 // 00854 // On a successful wait pull the status out of the IoStatus block. 00855 // 00856 00857 if (NT_SUCCESS( Status )) { 00858 00859 Status = IrpContext->Irp->IoStatus.Status; 00860 } 00861 } 00862 00863 DebugTrace(( -1, Dbg, "UdfReadSectors -> %08x\n", Status )); 00864 00865 // 00866 // Check whether we should raise in the error case. 00867 // 00868 00869 if (!NT_SUCCESS( Status ) && !ReturnError) { 00870 00871 UdfNormalizeAndRaiseStatus( IrpContext, Status ); 00872 } 00873 00874 return Status; 00875 }

VOID UdfSingleAsync IN PIRP_CONTEXT  IrpContext,
IN LONGLONG  ByteOffset,
IN ULONG  ByteCount
 

Definition at line 1642 of file deviosup.c.

References FlagOn, IoCallDriver, IoGetNextIrpStackLocation, IoSetCompletionRoutine, IRP_CONTEXT_FLAG_WAIT, IRP_MJ_READ, _IO_STACK_LOCATION::MajorFunction, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PIO_COMPLETION_ROUTINE, TRUE, UdfSingleAsyncCompletionRoutine(), UdfSingleSyncCompletionRoutine(), and VOID().

Referenced by UdfNonCachedRead().

01650 : 01651 01652 This routine reads one or more contiguous sectors from a device 01653 asynchronously, and is used if there is only one read necessary to 01654 complete the IRP. It implements the read by simply filling 01655 in the next stack frame in the Irp, and passing it on. The transfer 01656 occurs to the single buffer originally specified in the user request. 01657 01658 Arguments: 01659 01660 ByteOffset - Supplies the starting Logical Byte Offset to begin reading from 01661 01662 ByteCount - Supplies the number of bytes to read from the device 01663 01664 Return Value: 01665 01666 None. 01667 01668 --*/ 01669 01670 { 01671 PIO_STACK_LOCATION IrpSp; 01672 PIO_COMPLETION_ROUTINE CompletionRoutine; 01673 01674 PAGED_CODE(); 01675 01676 // 01677 // Set up things according to whether this is truely async. 01678 // 01679 01680 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 01681 01682 CompletionRoutine = UdfSingleSyncCompletionRoutine; 01683 01684 } else { 01685 01686 CompletionRoutine = UdfSingleAsyncCompletionRoutine; 01687 } 01688 01689 // 01690 // Set up the completion routine address in our stack frame. 01691 // 01692 01693 IoSetCompletionRoutine( IrpContext->Irp, 01694 CompletionRoutine, 01695 IrpContext->IoContext, 01696 TRUE, 01697 TRUE, 01698 TRUE ); 01699 01700 // 01701 // Setup the next IRP stack location in the associated Irp for the disk 01702 // driver beneath us. 01703 // 01704 01705 IrpSp = IoGetNextIrpStackLocation( IrpContext->Irp ); 01706 01707 // 01708 // Setup the Stack location to do a read from the disk driver. 01709 // 01710 01711 IrpSp->MajorFunction = IRP_MJ_READ; 01712 IrpSp->Parameters.Read.Length = ByteCount; 01713 IrpSp->Parameters.Read.ByteOffset.QuadPart = ByteOffset; 01714 01715 // 01716 // Issue the Io request 01717 // 01718 01719 // 01720 // If IoCallDriver returns an error, it has completed the Irp 01721 // and the error will be caught by our completion routines 01722 // and dealt with as a normal IO error. 01723 // 01724 01725 (VOID)IoCallDriver( IrpContext->Vcb->TargetDeviceObject, IrpContext->Irp ); 01726 01727 // 01728 // And return to our caller 01729 // 01730 01731 return; 01732 }

NTSTATUS UdfSingleAsyncCompletionRoutine IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context
 

Definition at line 2039 of file deviosup.c.

References ExReleaseResourceForThread, IoMarkIrpPending, _IRP::IoStatus, Irp, NT_SUCCESS, Resource, and UdfFreeIoContext.

Referenced by UdfSingleAsync().

02047 : 02048 02049 This is the completion routine for all asynchronous reads 02050 started via UdfSingleAsynch. 02051 02052 Arguments: 02053 02054 DeviceObject - Pointer to the file system device object. 02055 02056 Irp - Pointer to the Irp for this request. (This Irp will no longer 02057 be accessible after this routine returns.) 02058 02059 Context - The context parameter which was specified in the call to 02060 UdfSingleAsynch. 02061 02062 Return Value: 02063 02064 Currently always returns STATUS_SUCCESS. 02065 02066 --*/ 02067 02068 { 02069 // 02070 // Update the information field with the correct value for bytes read. 02071 // 02072 02073 Irp->IoStatus.Information = 0; 02074 02075 if (NT_SUCCESS( Irp->IoStatus.Status )) { 02076 02077 Irp->IoStatus.Information = ((PUDF_IO_CONTEXT) Context)->RequestedByteCount; 02078 } 02079 02080 // 02081 // Mark the Irp pending 02082 // 02083 02084 IoMarkIrpPending( Irp ); 02085 02086 // 02087 // Now release the resource 02088 // 02089 02090 ExReleaseResourceForThread( ((PUDF_IO_CONTEXT) Context)->Resource, 02091 ((PUDF_IO_CONTEXT) Context)->ResourceThreadId ); 02092 02093 // 02094 // and finally, free the context record. 02095 // 02096 02097 UdfFreeIoContext( (PUDF_IO_CONTEXT) Context ); 02098 return STATUS_SUCCESS; 02099 02100 UNREFERENCED_PARAMETER( DeviceObject ); 02101 }

NTSTATUS UdfSingleSyncCompletionRoutine IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context
 

Definition at line 1980 of file deviosup.c.

References FALSE, _IRP::IoStatus, Irp, KeSetEvent(), and NT_SUCCESS.

Referenced by UdfSingleAsync().

01988 : 01989 01990 This is the completion routine for all reads started via UdfSingleAsync. 01991 01992 The completion routine has has the following responsibilities: 01993 01994 It sets the event in the Context parameter to signal the caller 01995 that all of the asynch requests are done. 01996 01997 Arguments: 01998 01999 DeviceObject - Pointer to the file system device object. 02000 02001 Irp - Pointer to the Irp for this request. (This Irp will no longer 02002 be accessible after this routine returns.) 02003 02004 Context - The context parameter which was specified in the call to 02005 UdfSingleAsynch. 02006 02007 Return Value: 02008 02009 The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can 02010 immediately complete the Master Irp without being in a race condition 02011 with the IoCompleteRequest thread trying to decrement the IrpCount in 02012 the Master Irp. 02013 02014 --*/ 02015 02016 { 02017 // 02018 // Store the correct information field into the Irp. 02019 // 02020 02021 if (!NT_SUCCESS( Irp->IoStatus.Status )) { 02022 02023 Irp->IoStatus.Information = 0; 02024 } 02025 02026 KeSetEvent( &((PUDF_IO_CONTEXT)Context)->SyncEvent, 0, FALSE ); 02027 02028 return STATUS_MORE_PROCESSING_REQUIRED; 02029 02030 UNREFERENCED_PARAMETER( DeviceObject ); 02031 }

VOID UdfWaitSync IN PIRP_CONTEXT  IrpContext  ) 
 

Definition at line 1740 of file deviosup.c.

References Executive, FALSE, KeClearEvent, KernelMode, KeWaitForSingleObject(), NULL, and PAGED_CODE.

Referenced by UdfNonCachedRead().

01746 : 01747 01748 This routine waits for one or more previously started I/O requests 01749 from the above routines, by simply waiting on the event. 01750 01751 Arguments: 01752 01753 Return Value: 01754 01755 None 01756 01757 --*/ 01758 01759 { 01760 PAGED_CODE(); 01761 01762 KeWaitForSingleObject( &IrpContext->IoContext->SyncEvent, 01763 Executive, 01764 KernelMode, 01765 FALSE, 01766 NULL ); 01767 01768 KeClearEvent( &IrpContext->IoContext->SyncEvent ); 01769 01770 return; 01771 }


Generated on Sat May 15 19:43:26 2004 for test by doxygen 1.3.7