1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 FspDisp.c 8 9 Abstract: 10 11 This module implements the main dispatch procedure/thread for the Fat 12 Fsp 13 14 15 --*/ 16 17 #include "fatprocs.h" 18 19 // 20 // Internal support routine, spinlock wrapper. 21 // 22 23 PVOID 24 FatRemoveOverflowEntry ( 25 IN PVOLUME_DEVICE_OBJECT VolDo 26 ); 27 28 // 29 // Define our local debug trace level 30 // 31 32 #define Dbg (DEBUG_TRACE_FSP_DISPATCHER) 33 34 #ifdef ALLOC_PRAGMA 35 #pragma alloc_text(PAGE, FatFspDispatch) 36 #endif 37 38 39 VOID 40 NTAPI 41 FatFspDispatch ( 42 _In_ PVOID Context 43 ) 44 45 /*++ 46 47 Routine Description: 48 49 This is the main FSP thread routine that is executed to receive 50 and dispatch IRP requests. Each FSP thread begins its execution here. 51 There is one thread created at system initialization time and subsequent 52 threads created as needed. 53 54 Arguments: 55 56 57 Context - Supplies the thread id. 58 59 Return Value: 60 61 None - This routine never exits 62 63 --*/ 64 65 { 66 NTSTATUS Status = STATUS_SUCCESS; 67 68 69 PIRP Irp; 70 PIRP_CONTEXT IrpContext; 71 PIO_STACK_LOCATION IrpSp; 72 BOOLEAN VcbDeleted; 73 BOOLEAN ExceptionCompletedIrp = FALSE; 74 75 PVOLUME_DEVICE_OBJECT VolDo; 76 77 UCHAR MajorFunction = 0; 78 79 PAGED_CODE(); 80 81 IrpContext = (PIRP_CONTEXT)Context; 82 83 Irp = IrpContext->OriginatingIrp; 84 85 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 86 87 // 88 // Now because we are the Fsp we will force the IrpContext to 89 // indicate true on Wait. 90 // 91 92 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP); 93 94 // 95 // If this request has an associated volume device object, remember it. 96 // 97 98 if ( IrpSp->FileObject != NULL ) { 99 100 VolDo = CONTAINING_RECORD( IrpSp->DeviceObject, 101 VOLUME_DEVICE_OBJECT, 102 DeviceObject ); 103 } else { 104 105 VolDo = NULL; 106 } 107 108 // 109 // Now case on the function code. For each major function code, 110 // either call the appropriate FSP routine or case on the minor 111 // function and then call the FSP routine. The FSP routine that 112 // we call is responsible for completing the IRP, and not us. 113 // That way the routine can complete the IRP and then continue 114 // post processing as required. For example, a read can be 115 // satisfied right away and then read can be done. 116 // 117 // We'll do all of the work within an exception handler that 118 // will be invoked if ever some underlying operation gets into 119 // trouble (e.g., if FatReadSectorsSync has trouble). 120 // 121 122 while ( TRUE ) { 123 124 ExceptionCompletedIrp = FALSE; 125 126 DebugTrace(0, Dbg, "FatFspDispatch: Irp = %p\n", Irp); 127 128 // 129 // If this Irp was top level, note it in our thread local storage. 130 // 131 132 FsRtlEnterFileSystem(); 133 134 if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) { 135 136 IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP ); 137 138 } else { 139 140 IoSetTopLevelIrp( Irp ); 141 } 142 143 MajorFunction = IrpContext->MajorFunction; 144 145 _SEH2_TRY { 146 147 switch ( MajorFunction ) { 148 149 // 150 // For Create Operation, 151 // 152 153 case IRP_MJ_CREATE: 154 155 Status = FatCommonCreate( IrpContext, Irp ); 156 break; 157 158 // 159 // For close operations. We do a little kludge here in case 160 // this close causes a volume to go away. It will NULL the 161 // VolDo local variable so that we will not try to look at 162 // the overflow queue. 163 // 164 165 case IRP_MJ_CLOSE: 166 167 { 168 PVCB Vcb; 169 PFCB Fcb; 170 PCCB Ccb; 171 TYPE_OF_OPEN TypeOfOpen; 172 173 // 174 // Extract and decode the file object 175 // 176 177 TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb ); 178 179 // 180 // Do the close. We have a slightly different format 181 // for this call because of the async closes. 182 // 183 184 Status = FatCommonClose( Vcb, 185 Fcb, 186 Ccb, 187 TypeOfOpen, 188 TRUE, 189 TRUE, 190 &VcbDeleted ); 191 192 // 193 // If the VCB was deleted, do not try to access it later. 194 // 195 196 if (VcbDeleted) { 197 198 VolDo = NULL; 199 } 200 201 NT_ASSERT(Status == STATUS_SUCCESS); 202 203 FatCompleteRequest( IrpContext, Irp, Status ); 204 205 break; 206 } 207 208 // 209 // For read operations 210 // 211 212 case IRP_MJ_READ: 213 214 (VOID) FatCommonRead( IrpContext, Irp ); 215 break; 216 217 // 218 // For write operations, 219 // 220 221 case IRP_MJ_WRITE: 222 223 (VOID) FatCommonWrite( IrpContext, Irp ); 224 break; 225 226 // 227 // For Query Information operations, 228 // 229 230 case IRP_MJ_QUERY_INFORMATION: 231 232 (VOID) FatCommonQueryInformation( IrpContext, Irp ); 233 break; 234 235 // 236 // For Set Information operations, 237 // 238 239 case IRP_MJ_SET_INFORMATION: 240 241 (VOID) FatCommonSetInformation( IrpContext, Irp ); 242 break; 243 244 // 245 // For Query EA operations, 246 // 247 248 case IRP_MJ_QUERY_EA: 249 250 (VOID) FatCommonQueryEa( IrpContext, Irp ); 251 break; 252 253 // 254 // For Set EA operations, 255 // 256 257 case IRP_MJ_SET_EA: 258 259 (VOID) FatCommonSetEa( IrpContext, Irp ); 260 break; 261 262 // 263 // For Flush buffers operations, 264 // 265 266 case IRP_MJ_FLUSH_BUFFERS: 267 268 (VOID) FatCommonFlushBuffers( IrpContext, Irp ); 269 break; 270 271 // 272 // For Query Volume Information operations, 273 // 274 275 case IRP_MJ_QUERY_VOLUME_INFORMATION: 276 277 (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp ); 278 break; 279 280 // 281 // For Set Volume Information operations, 282 // 283 284 case IRP_MJ_SET_VOLUME_INFORMATION: 285 286 (VOID) FatCommonSetVolumeInfo( IrpContext, Irp ); 287 break; 288 289 // 290 // For File Cleanup operations, 291 // 292 293 case IRP_MJ_CLEANUP: 294 295 (VOID) FatCommonCleanup( IrpContext, Irp ); 296 break; 297 298 // 299 // For Directory Control operations, 300 // 301 302 case IRP_MJ_DIRECTORY_CONTROL: 303 304 (VOID) FatCommonDirectoryControl( IrpContext, Irp ); 305 break; 306 307 // 308 // For File System Control operations, 309 // 310 311 case IRP_MJ_FILE_SYSTEM_CONTROL: 312 313 (VOID) FatCommonFileSystemControl( IrpContext, Irp ); 314 break; 315 316 // 317 // For Lock Control operations, 318 // 319 320 case IRP_MJ_LOCK_CONTROL: 321 322 (VOID) FatCommonLockControl( IrpContext, Irp ); 323 break; 324 325 // 326 // For Device Control operations, 327 // 328 329 case IRP_MJ_DEVICE_CONTROL: 330 331 (VOID) FatCommonDeviceControl( IrpContext, Irp ); 332 break; 333 334 // 335 // For the Shutdown operation, 336 // 337 338 case IRP_MJ_SHUTDOWN: 339 340 (VOID) FatCommonShutdown( IrpContext, Irp ); 341 break; 342 343 // 344 // For plug and play operations. 345 // 346 347 case IRP_MJ_PNP: 348 349 // 350 // I don't believe this should ever occur, but allow for the unexpected. 351 // 352 353 (VOID) FatCommonPnp( IrpContext, Irp ); 354 break; 355 356 // 357 // For any other major operations, return an invalid 358 // request. 359 // 360 361 default: 362 363 FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST ); 364 break; 365 366 } 367 368 } _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) { 369 370 // 371 // We had some trouble trying to perform the requested 372 // operation, so we'll abort the I/O request with 373 // the error status that we get back from the 374 // execption code. 375 // 376 377 (VOID) FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() ); 378 ExceptionCompletedIrp = TRUE; 379 } _SEH2_END; 380 381 IoSetTopLevelIrp( NULL ); 382 383 FsRtlExitFileSystem(); 384 385 386 if (MajorFunction == IRP_MJ_CREATE && !ExceptionCompletedIrp && Status != STATUS_PENDING) { 387 388 // 389 // Creates are completed here. IrpContext is also freed here. 390 // 391 392 FatCompleteRequest( IrpContext, Irp, Status ); 393 } 394 395 // 396 // If there are any entries on this volume's overflow queue, service 397 // them. 398 // 399 400 if ( VolDo != NULL ) { 401 402 PVOID Entry; 403 404 // 405 // We have a volume device object so see if there is any work 406 // left to do in its overflow queue. 407 // 408 409 Entry = FatRemoveOverflowEntry( VolDo ); 410 411 // 412 // There wasn't an entry, break out of the loop and return to 413 // the Ex Worker thread. 414 // 415 416 if ( Entry == NULL ) { 417 418 break; 419 } 420 421 // 422 // Extract the IrpContext, Irp, and IrpSp, and loop. 423 // 424 425 IrpContext = CONTAINING_RECORD( Entry, 426 IRP_CONTEXT, 427 WorkQueueItem.List ); 428 429 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP); 430 431 Irp = IrpContext->OriginatingIrp; 432 433 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 434 435 continue; 436 437 } else { 438 439 break; 440 } 441 } 442 443 return; 444 } 445 446 447 // 448 // Internal support routine, spinlock wrapper. 449 // 450 451 PVOID 452 FatRemoveOverflowEntry ( 453 IN PVOLUME_DEVICE_OBJECT VolDo 454 ) 455 { 456 PVOID Entry; 457 KIRQL SavedIrql; 458 459 KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql ); 460 461 if (VolDo->OverflowQueueCount > 0) { 462 463 // 464 // There is overflow work to do in this volume so we'll 465 // decrement the Overflow count, dequeue the IRP, and release 466 // the Event 467 // 468 469 VolDo->OverflowQueueCount -= 1; 470 471 Entry = RemoveHeadList( &VolDo->OverflowQueue ); 472 473 } else { 474 475 VolDo->PostedRequestCount -= 1; 476 477 Entry = NULL; 478 } 479 480 KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql ); 481 482 return Entry; 483 } 484 485 486