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