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

Information | Donate

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

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

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

ReactOS Development > Doxygen

io.c
Go to the documentation of this file.
00001 /*************************************************************************
00002 *
00003 * File: io.c
00004 *
00005 * Module: Ext2 File System Driver (Kernel mode execution only)
00006 *
00007 * Description:
00008 *   This file contains low level disk io routines.
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_IO
00019 
00020 /*************************************************************************
00021 *
00022 * Function: Ext2PassDownMultiReadWriteIRP()
00023 *
00024 * Description:
00025 *   pass down multiple read IRPs as Associated IRPs
00026 *
00027 * Expected Interrupt Level (for execution) :
00028 *
00029 *  ?
00030 *
00031 * Return Value: STATUS_SUCCESS / STATUS_PENDING / Error
00032 *
00033 *************************************************************************/
00034 NTSTATUS NTAPI Ext2PassDownMultiReadWriteIRP( 
00035     PEXT2_IO_RUN            PtrIoRuns, 
00036     UINT                    Count, 
00037     ULONG                   TotalReadWriteLength,
00038     PtrExt2IrpContext       PtrIrpContext,
00039     PtrExt2FCB              PtrFCB,
00040     BOOLEAN                 SynchronousIo)
00041 {
00042     PIRP                PtrMasterIrp;
00043     PIRP                PtrAssociatedIrp;
00044     PIO_STACK_LOCATION  PtrIrpSp;
00045     PMDL                PtrMdl;
00046     PtrExt2VCB          PtrVCB;
00047     UINT                i;
00048     ULONG               BufferOffset;
00049     PEXT2_IO_CONTEXT    PtrIoContext = NULL;
00050     PKEVENT             PtrSyncEvent = NULL;
00051     ULONG               LogicalBlockSize;
00052     ULONG               ReadWriteLength;
00053 
00054     NTSTATUS RC = STATUS_SUCCESS;
00055 
00056     PtrVCB = PtrFCB->PtrVCB;
00057     PtrMasterIrp = PtrIrpContext->Irp;
00058     LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
00059 
00060     try
00061     {
00062         if( !SynchronousIo )
00063         {
00064             IoMarkIrpPending( PtrIrpContext->Irp );
00065             //  We will be returning STATUS_PENDING...
00066         }
00067 
00068         if( !PtrMasterIrp->MdlAddress )
00069         {
00070             Ext2LockCallersBuffer( PtrMasterIrp, TRUE, TotalReadWriteLength );
00071         }
00072 
00073         if( SynchronousIo )
00074         {
00075             PtrSyncEvent = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) )  );
00076             if ( !PtrSyncEvent )
00077             {
00078                 RC = STATUS_INSUFFICIENT_RESOURCES;
00079                 try_return();
00080             }
00081             KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
00082         }
00083         //
00084         //  Allocate and initialize a completion context
00085         //
00086         PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) )  );
00087         if ( !PtrIoContext )
00088         {
00089             RC = STATUS_INSUFFICIENT_RESOURCES;
00090             try_return();
00091         }
00092 
00093         RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
00094         PtrIoContext->Count = Count;
00095         PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
00096         PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
00097         PtrIoContext->PtrMasterIrp = PtrMasterIrp;
00098         PtrIoContext->PtrSyncEvent = PtrSyncEvent;
00099         PtrIoContext->ReadWriteLength = TotalReadWriteLength;
00100 
00101         
00102 
00103         for( ReadWriteLength = 0, BufferOffset = 0, i = 0; i < Count; i++, BufferOffset += ReadWriteLength )
00104         {
00105             
00106             ReadWriteLength = PtrIoRuns[ i].EndOffset - PtrIoRuns[ i].StartOffset;
00107             
00108             //
00109             //  Allocating an Associated IRP...
00110             //
00111             PtrAssociatedIrp = IoMakeAssociatedIrp( PtrMasterIrp,
00112                     (CCHAR) (PtrVCB->TargetDeviceObject->StackSize + 1 ) );
00113             PtrIoRuns[ i].PtrAssociatedIrp = PtrAssociatedIrp;
00114             ASSERT ( PtrAssociatedIrp );
00115             PtrMasterIrp->AssociatedIrp.IrpCount ++;
00116             
00117             //
00118             //  Allocating a Memory Descriptor List...
00119             //
00120             PtrMdl = IoAllocateMdl( (PCHAR) PtrMasterIrp->UserBuffer + BufferOffset, // Virtual Address
00121                 ReadWriteLength,    FALSE, FALSE, PtrAssociatedIrp );
00122             
00123             //
00124             //  and building a partial MDL...
00125             //
00126             IoBuildPartialMdl( PtrMasterIrp->MdlAddress,
00127                 PtrMdl, (PCHAR)PtrMasterIrp->UserBuffer + BufferOffset, ReadWriteLength );
00128 
00129             //
00130             //  Create an Irp stack location for ourselves...
00131             //
00132             IoSetNextIrpStackLocation( PtrAssociatedIrp );
00133             PtrIrpSp = IoGetCurrentIrpStackLocation( PtrAssociatedIrp );
00134 
00135             //
00136             //  Setup the Stack location to describe our read.
00137             //
00138             PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
00139             if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
00140             {
00141                 PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
00142                 PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = 
00143                     PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
00144             }
00145             else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
00146             {
00147                 PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
00148                 PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = 
00149                     PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
00150             }
00151 
00152             //  PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
00153             //  PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock;
00154 
00155 
00156             //
00157             //  Setup a completion routine...
00158             //
00159             IoSetCompletionRoutine( PtrAssociatedIrp, 
00160                         SynchronousIo ? 
00161                         Ext2MultiSyncCompletionRoutine : 
00162                         Ext2MultiAsyncCompletionRoutine,
00163                         PtrIoContext, TRUE, TRUE, TRUE );
00164 
00165             //
00166             //  Initialise the next stack location for the driver below us to use...
00167             //
00168             PtrIrpSp = IoGetNextIrpStackLocation( PtrAssociatedIrp );
00169             PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
00170             if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
00171             {
00172                 PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
00173                 PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
00174             }
00175             else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
00176             {
00177                 PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
00178                 PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
00179             }
00180 
00181             //  PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
00182             //  PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = 
00183             //      PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
00184         }
00185 
00186         for( i = 0; i < Count; i++ ) {
00187                     // DbgPrint("PASSING DOWN IRP %d TO TARGET DEVICE\n", i);
00188                     IoCallDriver( PtrVCB->TargetDeviceObject, PtrIoRuns[ i].PtrAssociatedIrp );
00189                 }
00190 
00191         if( SynchronousIo )
00192         {
00193             //
00194             //  Synchronous IO 
00195             //  Wait for the IO to complete...
00196             //
00197             DbgPrint("DEADLY WAIT (%d)\n", KeGetCurrentIrql());
00198             KeWaitForSingleObject( PtrSyncEvent,
00199                 Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
00200                         DbgPrint("DEADLY WAIT DONE\n");
00201             try_return();
00202         }
00203         else
00204         {
00205             //  Asynchronous IO...
00206             RC = STATUS_PENDING;
00207             try_return();
00208         }
00209     
00210         try_exit:   NOTHING;
00211     }
00212     finally 
00213     {
00214         if( PtrSyncEvent )
00215         {
00216             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrSyncEvent );
00217             ExFreePool( PtrSyncEvent );
00218         }
00219         if( PtrIoContext && ! ( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
00220         {
00221             //
00222             //  This means we are getting out of 
00223             //  this function without doing a read
00224             //  due to an error, maybe...
00225             //
00226             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrIoContext);
00227             ExFreePool( PtrIoContext );
00228         }
00229     }
00230     return(RC);
00231 }
00232 
00233 NTSTATUS NTAPI Ext2PassDownSingleReadWriteIRP(
00234     PtrExt2IrpContext   PtrIrpContext,
00235     PIRP                PtrIrp, 
00236     PtrExt2VCB          PtrVCB,
00237     LARGE_INTEGER       ByteOffset, 
00238     uint32              ReadWriteLength, 
00239     BOOLEAN             SynchronousIo)
00240 {
00241     NTSTATUS                RC = STATUS_SUCCESS;
00242 
00243     PEXT2_IO_CONTEXT        PtrIoContext = NULL;
00244     PKEVENT                 PtrSyncEvent = NULL;
00245 
00246     PIO_STACK_LOCATION  PtrIrpNextSp = NULL;
00247 
00248     try
00249     {
00250         if( !PtrIrp->MdlAddress )
00251         {
00252             Ext2LockCallersBuffer( PtrIrp, TRUE, ReadWriteLength );
00253         }
00254 
00255 
00256         if( SynchronousIo )
00257         {
00258             PtrSyncEvent = Ext2AllocatePool( NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) )  );
00259             if ( !PtrSyncEvent )
00260             {
00261                 RC = STATUS_INSUFFICIENT_RESOURCES;
00262                 try_return();
00263             }
00264             KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
00265         }
00266 
00267         //
00268         //  Allocate and initialize a completion context
00269         //
00270         PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) )  );
00271         if ( !PtrIoContext )
00272         {
00273             RC = STATUS_INSUFFICIENT_RESOURCES;
00274             try_return();
00275         }
00276 
00277         RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
00278         PtrIoContext->Count = 1;
00279         PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
00280         PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
00281         PtrIoContext->PtrMasterIrp = NULL;
00282         PtrIoContext->PtrSyncEvent = PtrSyncEvent;
00283         PtrIoContext->ReadWriteLength = ReadWriteLength;
00284 
00285         IoSetCompletionRoutine( PtrIrp, 
00286             SynchronousIo ? 
00287             Ext2SingleSyncCompletionRoutine: 
00288             Ext2SingleAsyncCompletionRoutine,
00289             PtrIoContext, TRUE, TRUE, TRUE );
00290 
00291         //
00292         //  Setup the next IRP stack location in the associated Irp for the disk
00293         //  driver beneath us.
00294         //
00295         PtrIrpNextSp = IoGetNextIrpStackLocation( PtrIrp );
00296 
00297         //
00298         //  Setup the Stack location to do a read from the disk driver.
00299         //
00300         PtrIrpNextSp->MajorFunction = PtrIrpContext->MajorFunction;
00301         if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
00302         {
00303             PtrIrpNextSp->Parameters.Read.Length = ReadWriteLength;
00304             PtrIrpNextSp->Parameters.Read.ByteOffset = ByteOffset;
00305         }
00306         else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
00307         {
00308             PtrIrpNextSp->Parameters.Write.Length = ReadWriteLength;
00309             PtrIrpNextSp->Parameters.Write.ByteOffset = ByteOffset;
00310         }
00311         //
00312         //  Issue the read / write request
00313         //
00314         RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
00315 
00316         if( SynchronousIo )
00317         {
00318             //
00319             //  Wait for completion...
00320             //
00321             RC = KeWaitForSingleObject( &PtrIoContext->PtrSyncEvent,
00322                         Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
00323 
00324             RC = STATUS_SUCCESS;
00325         }
00326         else
00327         {
00328             RC = STATUS_PENDING;
00329         }
00330 
00331         try_exit:   NOTHING;
00332     }
00333     finally 
00334     {
00335         if( PtrSyncEvent )
00336         {
00337             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrSyncEvent );
00338             ExFreePool( PtrSyncEvent );
00339         }
00340         if( PtrIoContext && !( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
00341         {
00342             //
00343             //  This means we are getting out of 
00344             //  this function without doing a read / write
00345             //  due to an error, maybe...
00346             //
00347             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrIoContext );
00348             ExFreePool( PtrIoContext );
00349         }
00350     }
00351     return RC;
00352 }
00353 
00354 
00355 /*************************************************************************
00356 *
00357 * Function: Ext2SingleSyncCompletionRoutine()
00358 *
00359 * Description:
00360 *   Synchronous I/O Completion Routine
00361 *
00362 * Expected Interrupt Level (for execution) :
00363 *
00364 *  ?
00365 *
00366 * Return Value: NTSTATUS - STATUS_SUCCESS(always)
00367 *
00368 *************************************************************************/
00369 NTSTATUS NTAPI Ext2SingleSyncCompletionRoutine(
00370     IN PDEVICE_OBJECT DeviceObject,
00371     IN PIRP Irp,
00372     IN PVOID Contxt
00373     )
00374 {
00375     PEXT2_IO_CONTEXT PtrContext = Contxt;
00376 
00377     if( Irp->PendingReturned  )
00378         IoMarkIrpPending( Irp );
00379     
00380     ASSERT( PtrContext );
00381     ASSERT( PtrContext->NodeIdentifier.NodeType == EXT2_NODE_TYPE_IO_CONTEXT );
00382 
00383     KeSetEvent( PtrContext->PtrSyncEvent, 0, FALSE );
00384     DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrContext );
00385     ExFreePool( PtrContext );
00386 
00387     return STATUS_SUCCESS;
00388 }
00389 
00390 /*************************************************************************
00391 *
00392 * Function: Ext2SingleAsyncCompletionRoutine()
00393 *
00394 * Description:
00395 *   Asynchronous I/O Completion Routine
00396 *
00397 * Expected Interrupt Level (for execution) :
00398 *
00399 *  ?
00400 *
00401 * Return Value: NTSTATUS - STATUS_SUCCESS(always)
00402 *
00403 *************************************************************************/
00404 NTSTATUS NTAPI Ext2SingleAsyncCompletionRoutine(
00405     IN PDEVICE_OBJECT DeviceObject,
00406     IN PIRP Irp,
00407     IN PVOID Contxt
00408     )
00409 {
00410     PEXT2_IO_CONTEXT PtrContext = Contxt;
00411 
00412     if( Irp->PendingReturned  )
00413         IoMarkIrpPending( Irp );
00414     
00415     ASSERT( PtrContext );
00416     ASSERT( PtrContext->NodeIdentifier.NodeType == EXT2_NODE_TYPE_IO_CONTEXT );
00417 
00418     DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrContext );
00419     ExFreePool( PtrContext );
00420 
00421     return STATUS_SUCCESS;
00422 }
00423 
00424 /*************************************************************************
00425 *
00426 * Function: Ext2MultiSyncCompletionRoutine()
00427 *
00428 * Description:
00429 *   Synchronous I/O Completion Routine
00430 *
00431 * Expected Interrupt Level (for execution) :
00432 *
00433 *  ?
00434 *
00435 * Return Value: NTSTATUS - STATUS_SUCCESS(always)
00436 *
00437 *************************************************************************/
00438 NTSTATUS NTAPI Ext2MultiSyncCompletionRoutine (
00439     IN PDEVICE_OBJECT DeviceObject,
00440     IN PIRP Irp,
00441     IN PVOID Contxt
00442     )
00443 {
00444 
00445     PEXT2_IO_CONTEXT PtrContext = Contxt;
00446     ASSERT( PtrContext );
00447 
00448     if( Irp->PendingReturned )
00449     {
00450         IoMarkIrpPending( Irp );
00451     }
00452 
00453     if (!NT_SUCCESS( Irp->IoStatus.Status )) 
00454     {
00455         PtrContext->PtrMasterIrp->IoStatus.Status = Irp->IoStatus.Status;
00456     }
00457 
00458     if (InterlockedDecrement( &PtrContext->Count ) == 0)
00459     {
00460         if ( NT_SUCCESS( PtrContext->PtrMasterIrp->IoStatus.Status ) )
00461         {
00462             PtrContext->PtrMasterIrp->IoStatus.Information = PtrContext->ReadWriteLength;
00463         }
00464         else
00465         {
00466             PtrContext->PtrMasterIrp->IoStatus.Information = 0;
00467         }
00468 
00469         KeSetEvent( PtrContext->PtrSyncEvent, 0, FALSE );
00470         DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrContext );
00471         ExFreePool( PtrContext );
00472     }
00473 
00474     //
00475     //  The master Irp will be automatically completed 
00476     //  when all the associated IRPs are completed
00477     //
00478     return STATUS_SUCCESS;
00479 }
00480 
00481 /*************************************************************************
00482 *
00483 * Function: Ext2MultiAsyncCompletionRoutine()
00484 *
00485 * Description:
00486 *   Asynchronous I/O Completion Routine
00487 *
00488 * Expected Interrupt Level (for execution) :
00489 *
00490 *  ?
00491 *
00492 * Return Value: NTSTATUS - STATUS_SUCCESS(always)
00493 *
00494 *************************************************************************/
00495 NTSTATUS NTAPI Ext2MultiAsyncCompletionRoutine (
00496     IN PDEVICE_OBJECT DeviceObject,
00497     IN PIRP Irp,
00498     IN PVOID Contxt
00499     )
00500 {
00501 
00502     PEXT2_IO_CONTEXT PtrContext = Contxt;
00503     ASSERT( PtrContext );
00504     
00505     if( Irp->PendingReturned )
00506     {
00507         IoMarkIrpPending( Irp );
00508     }
00509 
00510     if (!NT_SUCCESS( Irp->IoStatus.Status )) 
00511     {
00512         PtrContext->PtrMasterIrp->IoStatus.Status = Irp->IoStatus.Status;
00513     }
00514 
00515     if (InterlockedDecrement( &PtrContext->Count ) == 0)
00516     {
00517         if ( NT_SUCCESS( PtrContext->PtrMasterIrp->IoStatus.Status ) )
00518         {
00519             PtrContext->PtrMasterIrp->IoStatus.Information = PtrContext->ReadWriteLength;
00520         }
00521         else
00522         {
00523             PtrContext->PtrMasterIrp->IoStatus.Information = 0;
00524         }
00525         DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrContext );
00526         ExFreePool( PtrContext );
00527     }
00528 
00529     //
00530     //  The master Irp will be automatically completed 
00531     //  when all the associated IRPs are completed
00532     //  Returning STATUS_SUCCESS to continue postprocessing...
00533     //
00534     return STATUS_SUCCESS;
00535 }

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

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