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

close.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Close.c 00008 00009 Abstract: 00010 00011 This module implements the File Close routine for Udfs called by the 00012 Fsd/Fsp dispatch routines. 00013 00014 The close operation interacts with both the async and delayed close queues 00015 in the UdfData structure. Since close may be called recursively we may 00016 violate the locking order in acquiring the Vcb or Fcb. In this case 00017 we may move the request to the async close queue. If this is the last 00018 reference on the Fcb and there is a chance the user may reopen this 00019 file again soon we would like to defer the close. In this case we 00020 may move the request to the delayed close queue. 00021 00022 Once we are past the decode file operation there is no need for the 00023 file object. If we are moving the request to either of the work 00024 queues then we remember all of the information from the file object and 00025 complete the request with STATUS_SUCCESS. The Io system can then 00026 reuse the file object and we can complete the request when convenient. 00027 00028 The async close queue consists of requests which we would like to 00029 complete as soon as possible. They are queued using the original 00030 IrpContext where some of the fields have been overwritten with 00031 information from the file object. We will extract this information, 00032 cleanup the IrpContext and then call the close worker routine. 00033 00034 The delayed close queue consists of requests which we would like to 00035 defer the close for. We keep size of this list within a range 00036 determined by the size of the system. We let it grow to some maximum 00037 value and then shrink to some minimum value. We allocate a small 00038 structure which contains the key information from the file object 00039 and use this information along with an IrpContext on the stack 00040 to complete the request. 00041 00042 Author: 00043 00044 Dan Lovinger [DanLo] 04-Nov-1996 00045 00046 Revision History: 00047 00048 --*/ 00049 00050 #include "UdfProcs.h" 00051 00052 // 00053 // The Bug check file id for this module 00054 // 00055 00056 #define BugCheckFileId (UDFS_BUG_CHECK_CLOSE) 00057 00058 // 00059 // The local debug trace level 00060 // 00061 00062 #define Dbg (UDFS_DEBUG_LEVEL_CLOSE) 00063 00064 // 00065 // Local support routines 00066 // 00067 00068 BOOLEAN 00069 UdfCommonClosePrivate ( 00070 IN PIRP_CONTEXT IrpContext, 00071 IN PVCB Vcb, 00072 IN PFCB Fcb, 00073 IN ULONG UserReference, 00074 IN BOOLEAN FromFsd 00075 ); 00076 00077 VOID 00078 UdfQueueClose ( 00079 IN PIRP_CONTEXT IrpContext, 00080 IN PFCB Fcb, 00081 IN ULONG UserReference, 00082 IN BOOLEAN DelayedClose 00083 ); 00084 00085 PIRP_CONTEXT 00086 UdfRemoveClose ( 00087 IN PVCB Vcb OPTIONAL 00088 ); 00089 00090 #ifdef ALLOC_PRAGMA 00091 #pragma alloc_text(PAGE, UdfCommonClose) 00092 #pragma alloc_text(PAGE, UdfCommonClosePrivate) 00093 #pragma alloc_text(PAGE, UdfQueueClose) 00094 #pragma alloc_text(PAGE, UdfRemoveClose) 00095 #endif 00096 00097 00098 VOID 00099 UdfFspClose ( 00100 IN PVCB Vcb OPTIONAL 00101 ) 00102 00103 /*++ 00104 00105 Routine Description: 00106 00107 This routine is called to process the close queues in the UdfData. If the 00108 Vcb is passed then we want to remove all of the closes for this Vcb. 00109 Otherwise we will do as many of the delayed closes as we need to do. 00110 00111 Arguments: 00112 00113 Vcb - If specified then we are looking for all of the closes for the 00114 given Vcb. 00115 00116 Return Value: 00117 00118 None 00119 00120 --*/ 00121 00122 { 00123 PIRP_CONTEXT IrpContext; 00124 IRP_CONTEXT StackIrpContext; 00125 00126 THREAD_CONTEXT ThreadContext; 00127 00128 PFCB Fcb; 00129 ULONG UserReference; 00130 00131 ULONG VcbHoldCount = 0; 00132 PVCB CurrentVcb = NULL; 00133 00134 BOOLEAN ReleaseUdfData = FALSE; 00135 00136 PAGED_CODE(); 00137 00138 // 00139 // Check input. 00140 // 00141 00142 ASSERT_OPTIONAL_VCB( Vcb ); 00143 00144 FsRtlEnterFileSystem(); 00145 00146 // 00147 // Continue processing until there are no more closes to process. 00148 // 00149 00150 while (IrpContext = UdfRemoveClose( Vcb )) { 00151 00152 // 00153 // If we don't have an IrpContext then use the one on the stack. 00154 // Initialize it for this request. 00155 // 00156 00157 if (SafeNodeType( IrpContext ) != UDFS_NTC_IRP_CONTEXT ) { 00158 00159 // 00160 // Update the local values from the IrpContextLite. 00161 // 00162 00163 Fcb = ((PIRP_CONTEXT_LITE) IrpContext)->Fcb; 00164 UserReference = ((PIRP_CONTEXT_LITE) IrpContext)->UserReference; 00165 00166 // 00167 // Update the stack irp context with the values from the 00168 // IrpContextLite. 00169 // 00170 00171 UdfInitializeStackIrpContext( &StackIrpContext, 00172 (PIRP_CONTEXT_LITE) IrpContext ); 00173 00174 // 00175 // Free the IrpContextLite. 00176 // 00177 00178 UdfFreeIrpContextLite( (PIRP_CONTEXT_LITE) IrpContext ); 00179 00180 // 00181 // Remember we have the IrpContext from the stack. 00182 // 00183 00184 IrpContext = &StackIrpContext; 00185 00186 // 00187 // Otherwise cleanup the existing IrpContext. 00188 // 00189 00190 } else { 00191 00192 // 00193 // Remember the Fcb and user reference count. 00194 // 00195 00196 Fcb = (PFCB) IrpContext->Irp; 00197 IrpContext->Irp = NULL; 00198 00199 UserReference = (ULONG) IrpContext->ExceptionStatus; 00200 IrpContext->ExceptionStatus = STATUS_SUCCESS; 00201 } 00202 00203 // 00204 // We have an IrpContext. Now we need to set the top level thread 00205 // context. 00206 // 00207 00208 SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS ); 00209 00210 // 00211 // If we were given a Vcb then there is a request on top of this. 00212 // 00213 00214 if (ARGUMENT_PRESENT( Vcb )) { 00215 00216 ClearFlag( IrpContext->Flags, 00217 IRP_CONTEXT_FLAG_TOP_LEVEL | IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS ); 00218 } 00219 00220 UdfSetThreadContext( IrpContext, &ThreadContext ); 00221 00222 // 00223 // If we have hit the maximum number of requests to process without 00224 // releasing the Vcb then release the Vcb now. If we are holding 00225 // a different Vcb to this one then release the previous Vcb. 00226 // 00227 // In either case acquire the current Vcb. 00228 // 00229 // We use the MinDelayedCloseCount from the UdfData since it is 00230 // a convenient value based on the system size. Only thing we are trying 00231 // to do here is prevent this routine starving other threads which 00232 // may need this Vcb exclusively. 00233 // 00234 00235 ReleaseUdfData = !ARGUMENT_PRESENT( Vcb ) && 00236 (Fcb->Vcb->VcbCondition != VcbMounted) && 00237 (Fcb->Vcb->VcbCondition != VcbMountInProgress) && 00238 (Fcb->Vcb->VcbCleanup == 0); 00239 00240 if (ReleaseUdfData || 00241 (VcbHoldCount > UdfData.MinDelayedCloseCount) || 00242 (Fcb->Vcb != CurrentVcb)) { 00243 00244 if (CurrentVcb != NULL) { 00245 00246 UdfReleaseVcb( IrpContext, CurrentVcb ); 00247 } 00248 00249 if (ReleaseUdfData) { 00250 00251 UdfAcquireUdfData( IrpContext ); 00252 } 00253 00254 CurrentVcb = Fcb->Vcb; 00255 UdfAcquireVcbShared( IrpContext, CurrentVcb, FALSE ); 00256 00257 VcbHoldCount = 0; 00258 00259 } else { 00260 00261 VcbHoldCount += 1; 00262 } 00263 00264 DebugTrace(( +1, Dbg, 00265 "UdfFspClose, Fcb %08x %4s Vcb %d/%d Fcb %d/%d\n", 00266 Fcb, 00267 ( UserReference? "USER" : "SYS" ), 00268 CurrentVcb->VcbReference, 00269 CurrentVcb->VcbUserReference, 00270 Fcb->FcbReference, 00271 Fcb->FcbUserReference )); 00272 00273 // 00274 // Call our worker routine to perform the close operation. 00275 // 00276 00277 UdfCommonClosePrivate( IrpContext, CurrentVcb, Fcb, UserReference, FALSE ); 00278 00279 // 00280 // If the reference count on this Vcb is below our residual reference 00281 // then check if we should dismount the volume. 00282 // 00283 00284 if (ReleaseUdfData) { 00285 00286 UdfReleaseVcb( IrpContext, CurrentVcb ); 00287 UdfCheckForDismount( IrpContext, CurrentVcb, FALSE ); 00288 00289 CurrentVcb = NULL; 00290 00291 UdfReleaseUdfData( IrpContext ); 00292 ReleaseUdfData = FALSE; 00293 } 00294 00295 // 00296 // Complete the current request to cleanup the IrpContext. 00297 // 00298 00299 UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); 00300 00301 DebugTrace(( -1, Dbg, "UdfFspClose -> VOID\n" )); 00302 } 00303 00304 // 00305 // Release any Vcb we may still hold. 00306 // 00307 00308 if (CurrentVcb != NULL) { 00309 00310 UdfReleaseVcb( IrpContext, CurrentVcb ); 00311 } 00312 00313 FsRtlExitFileSystem(); 00314 return; 00315 } 00316 00317 00318 NTSTATUS 00319 UdfCommonClose ( 00320 IN PIRP_CONTEXT IrpContext, 00321 IN PIRP Irp 00322 ) 00323 00324 /*++ 00325 00326 Routine Description: 00327 00328 This routine is the Fsd entry for the close operation. We decode the file 00329 object to find the UDFS structures and type of open. We call our internal 00330 worker routine to perform the actual work. If the work wasn't completed 00331 then we post to one of our worker queues. The Ccb isn't needed after this 00332 point so we delete the Ccb and return STATUS_SUCCESS to our caller in all 00333 cases. 00334 00335 Arguments: 00336 00337 Irp - Supplies the Irp to process 00338 00339 Return Value: 00340 00341 STATUS_SUCCESS 00342 00343 --*/ 00344 00345 { 00346 TYPE_OF_OPEN TypeOfOpen; 00347 00348 PVCB Vcb; 00349 PFCB Fcb; 00350 PCCB Ccb; 00351 ULONG UserReference = 0; 00352 00353 BOOLEAN DelayedClose; 00354 BOOLEAN ReleaseUdfData = FALSE; 00355 00356 PAGED_CODE(); 00357 00358 // 00359 // Check input. 00360 // 00361 00362 ASSERT_IRP_CONTEXT( IrpContext ); 00363 ASSERT_IRP( Irp ); 00364 00365 // 00366 // If we were called with our file system device object instead of a 00367 // volume device object, just complete this request with STATUS_SUCCESS. 00368 // 00369 00370 if (IrpContext->Vcb == NULL) { 00371 00372 UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); 00373 return STATUS_SUCCESS; 00374 } 00375 00376 // 00377 // Decode the file object to get the type of open and Fcb/Ccb. 00378 // 00379 00380 TypeOfOpen = UdfDecodeFileObject( IoGetCurrentIrpStackLocation( Irp )->FileObject, 00381 &Fcb, 00382 &Ccb ); 00383 00384 // 00385 // No work to do for unopened file objects. 00386 // 00387 00388 if (TypeOfOpen == UnopenedFileObject) { 00389 00390 UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); 00391 00392 return STATUS_SUCCESS; 00393 } 00394 00395 Vcb = Fcb->Vcb; 00396 00397 // 00398 // Call the worker routine to perform the actual work. This routine 00399 // should never raise except for a fatal error. 00400 // 00401 00402 if (Ccb != NULL) { 00403 00404 UserReference = 1; 00405 00406 // 00407 // We can always deallocate the Ccb if present. 00408 // 00409 00410 UdfDeleteCcb( IrpContext, Ccb ); 00411 } 00412 00413 // 00414 // If this is a user file or directory then check if we should post 00415 // this to the delayed close queue. This has to be the last reference 00416 // for a user file or directory open. 00417 // 00418 00419 if ((Vcb->VcbCondition == VcbMounted) && 00420 (Fcb->FcbReference == 1) && 00421 ((TypeOfOpen == UserFileOpen) || 00422 (TypeOfOpen == UserDirectoryOpen))) { 00423 00424 UdfQueueClose( IrpContext, Fcb, UserReference, TRUE ); 00425 IrpContext = NULL; 00426 00427 // 00428 // Otherwise try to process this close. Post to the async close queue 00429 // if we can't acquire all of the resources. 00430 // 00431 00432 } else { 00433 00434 // 00435 // If we may be dismounting this volume then acquire the UdfData 00436 // resource. 00437 // 00438 // Since we now must make volumes go away as soon as reasonable after 00439 // the last user handles closes, key off of the cleanup count. It is 00440 // OK to do this more than neccesary. Since this Fcb could be holding 00441 // a number of other Fcbs (and thus their references), a simple check 00442 // on reference count is not appropriate. 00443 // 00444 00445 if ((Vcb->VcbCleanup == 0) && 00446 (Vcb->VcbCondition != VcbMounted) && 00447 (Vcb->VcbCondition != VcbMountInProgress) && 00448 FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS )) { 00449 00450 UdfAcquireUdfData( IrpContext ); 00451 ReleaseUdfData = TRUE; 00452 } 00453 00454 if (!UdfCommonClosePrivate( IrpContext, Vcb, Fcb, UserReference, TRUE )) { 00455 00456 // 00457 // If we didn't complete the request then post the request as needed. 00458 // 00459 00460 UdfQueueClose( IrpContext, Fcb, UserReference, FALSE ); 00461 IrpContext = NULL; 00462 00463 // 00464 // Check whether we should be dismounting the volume and then complete 00465 // the request. 00466 // 00467 00468 } else if (ReleaseUdfData) { 00469 00470 UdfCheckForDismount( IrpContext, Vcb, FALSE ); 00471 } 00472 } 00473 00474 // 00475 // Always complete this request with STATUS_SUCCESS. 00476 // 00477 00478 UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); 00479 00480 if (ReleaseUdfData) { 00481 00482 UdfReleaseUdfData( IrpContext ); 00483 } 00484 00485 // 00486 // Always return STATUS_SUCCESS for closes. 00487 // 00488 00489 return STATUS_SUCCESS; 00490 } 00491 00492 00493 // 00494 // Local support routine 00495 // 00496 00497 BOOLEAN 00498 UdfCommonClosePrivate ( 00499 IN PIRP_CONTEXT IrpContext, 00500 IN PVCB Vcb, 00501 IN PFCB Fcb, 00502 IN ULONG UserReference, 00503 IN BOOLEAN FromFsd 00504 ) 00505 00506 /*++ 00507 00508 Routine Description: 00509 00510 This is the worker routine for the close operation. We can be called in 00511 an Fsd thread or from a worker Fsp thread. If called from the Fsd thread 00512 then we acquire the resources without waiting. Otherwise we know it is 00513 safe to wait. 00514 00515 We check to see whether we should post this request to the delayed close 00516 queue. If we are to process the close here then we acquire the Vcb and 00517 Fcb. We will adjust the counts and call our teardown routine to see 00518 if any of the structures should go away. 00519 00520 Arguments: 00521 00522 Vcb - Vcb for this volume. 00523 00524 Fcb - Fcb for this request. 00525 00526 UserReference - Number of user references for this file object. This is 00527 zero for an internal stream. 00528 00529 FromFsd - This request was called from an Fsd thread. Indicates whether 00530 we should wait to acquire resources. 00531 00532 Return Value: 00533 00534 BOOLEAN - TRUE if this thread processed the close, FALSE otherwise. 00535 00536 --*/ 00537 00538 { 00539 BOOLEAN CompletedClose; 00540 BOOLEAN RemovedFcb; 00541 00542 PAGED_CODE(); 00543 00544 // 00545 // Check inputs. 00546 // 00547 00548 ASSERT_IRP_CONTEXT( IrpContext ); 00549 ASSERT_VCB( Vcb ); 00550 ASSERT_FCB( Fcb ); 00551 00552 // 00553 // Try to acquire the Vcb and Fcb. If we can't acquire them then return 00554 // and let our caller know he should post the request to the async 00555 // queue. 00556 // 00557 00558 if (UdfAcquireVcbShared( IrpContext, Vcb, FromFsd )) { 00559 00560 if (!UdfAcquireFcbExclusive( IrpContext, Fcb, FromFsd )) { 00561 00562 // 00563 // We couldn't get the Fcb. Release the Vcb and let our caller 00564 // know to post this request. 00565 // 00566 00567 UdfReleaseVcb( IrpContext, Vcb ); 00568 return FALSE; 00569 } 00570 00571 // 00572 // We didn't get the Vcb. Let our caller know to post this request. 00573 // 00574 00575 } else { 00576 00577 return FALSE; 00578 } 00579 00580 // 00581 // Lock the Vcb and decrement the reference counts. 00582 // 00583 00584 UdfLockVcb( IrpContext, Vcb ); 00585 00586 DebugTrace(( +1, Dbg, 00587 "UdfCommonClosePrivate, Fcb %08x %4s Vcb %d/%d Fcb %d/%d\n", Fcb, 00588 ( UserReference? "USER" : "SYS" ), 00589 Vcb->VcbReference, 00590 Vcb->VcbUserReference, 00591 Fcb->FcbReference, 00592 Fcb->FcbUserReference )); 00593 00594 UdfDecrementReferenceCounts( IrpContext, Fcb, 1, UserReference ); 00595 00596 DebugTrace(( +0, Dbg, 00597 "UdfCommonClosePrivate, Vcb %d/%d Fcb %d/%d\n", 00598 Vcb->VcbReference, 00599 Vcb->VcbUserReference, 00600 Fcb->FcbReference, 00601 Fcb->FcbUserReference )); 00602 00603 UdfUnlockVcb( IrpContext, Vcb ); 00604 00605 // 00606 // Call our teardown routine to see if this object can go away. 00607 // If we don't remove the Fcb then release it. 00608 // 00609 00610 UdfTeardownStructures( IrpContext, Fcb, FALSE, &RemovedFcb ); 00611 00612 if (!RemovedFcb) { 00613 00614 UdfReleaseFcb( IrpContext, Fcb ); 00615 } 00616 00617 DebugTrace(( -1, Dbg, 00618 "UdfCommonClosePrivate, RemovedFcb %08x -> %c\n", 00619 Fcb, 00620 ( RemovedFcb? 'T' : 'F' ))); 00621 00622 // 00623 // Release the Vcb and return to our caller. Let him know we completed 00624 // this request. 00625 // 00626 00627 UdfReleaseVcb( IrpContext, Vcb ); 00628 00629 return TRUE; 00630 } 00631 00632 00633 VOID 00634 UdfQueueClose ( 00635 IN PIRP_CONTEXT IrpContext, 00636 IN PFCB Fcb, 00637 IN ULONG UserReference, 00638 IN BOOLEAN DelayedClose 00639 ) 00640 00641 /*++ 00642 00643 Routine Description: 00644 00645 This routine is called to queue a request to either the async or delayed 00646 close queue. For the delayed queue we need to allocate a smaller 00647 structure to contain the information about the file object. We do 00648 that so we don't put the larger IrpContext structures into this long 00649 lived queue. If we can allocate this structure then we put this 00650 on the async queue instead. 00651 00652 Arguments: 00653 00654 Fcb - Fcb for this file object. 00655 00656 UserReference - Number of user references for this file object. This is 00657 zero for an internal stream. 00658 00659 DelayedClose - Indicates whether this should go on the async or delayed 00660 close queue. 00661 00662 Return Value: 00663 00664 None 00665 00666 --*/ 00667 00668 { 00669 PIRP_CONTEXT_LITE IrpContextLite = NULL; 00670 BOOLEAN StartWorker = FALSE; 00671 00672 PAGED_CODE(); 00673 00674 // 00675 // Check inputs. 00676 // 00677 00678 ASSERT_IRP_CONTEXT( IrpContext ); 00679 ASSERT_FCB( Fcb ); 00680 00681 // 00682 // Start with the delayed queue request. We can move this to the async 00683 // queue if there is an allocation failure. 00684 // 00685 00686 if (DelayedClose) { 00687 00688 // 00689 // Try to allocate non-paged pool for the IRP_CONTEXT_LITE. 00690 // 00691 00692 IrpContextLite = UdfCreateIrpContextLite( IrpContext ); 00693 } 00694 00695 // 00696 // We want to clear the top level context in this thread if 00697 // necessary. Call our cleanup routine to do the work. 00698 // 00699 00700 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); 00701 UdfCleanupIrpContext( IrpContext, TRUE ); 00702 00703 // 00704 // Synchronize with the UdfData lock. 00705 // 00706 00707 UdfLockUdfData(); 00708 00709 DebugTrace(( +1, Dbg, 00710 "UdfQueueClose, Fcb %08x %4s %5s\n", 00711 Fcb, 00712 ( UserReference? "USER" : "SYS" ), 00713 ( IrpContextLite? "DELAY" : "ASYNC" ))); 00714 00715 00716 // 00717 // If we have an IrpContext then put the request on the delayed close queue. 00718 // 00719 00720 if (IrpContextLite != NULL) { 00721 00722 // 00723 // Initialize the IrpContextLite. 00724 // 00725 00726 IrpContextLite->NodeTypeCode = UDFS_NTC_IRP_CONTEXT_LITE; 00727 IrpContextLite->NodeByteSize = sizeof( IRP_CONTEXT_LITE ); 00728 IrpContextLite->Fcb = Fcb; 00729 IrpContextLite->UserReference = UserReference; 00730 IrpContextLite->RealDevice = IrpContext->RealDevice; 00731 00732 // 00733 // Add this to the delayed close list and increment 00734 // the count. 00735 // 00736 00737 InsertTailList( &UdfData.DelayedCloseQueue, 00738 &IrpContextLite->DelayedCloseLinks ); 00739 00740 UdfData.DelayedCloseCount += 1; 00741 00742 // 00743 // If we are above our threshold then start the delayed 00744 // close operation. 00745 // 00746 00747 if (UdfData.DelayedCloseCount > UdfData.MaxDelayedCloseCount) { 00748 00749 UdfData.ReduceDelayedClose = TRUE; 00750 00751 if (!UdfData.FspCloseActive) { 00752 00753 UdfData.FspCloseActive = TRUE; 00754 StartWorker = TRUE; 00755 } 00756 } 00757 00758 // 00759 // Unlock the global data. 00760 // 00761 00762 UdfUnlockUdfData(); 00763 00764 // 00765 // Cleanup the IrpContext. 00766 // 00767 00768 UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); 00769 00770 // 00771 // Otherwise drop into the async case below. 00772 // 00773 00774 } else { 00775 00776 // 00777 // Store the information about the file object into the IrpContext. 00778 // 00779 00780 IrpContext->Irp = (PIRP) Fcb; 00781 IrpContext->ExceptionStatus = (NTSTATUS) UserReference; 00782 00783 // 00784 // Add this to the async close list and increment the count. 00785 // 00786 00787 InsertTailList( &UdfData.AsyncCloseQueue, 00788 &IrpContext->WorkQueueItem.List ); 00789 00790 UdfData.AsyncCloseCount += 1; 00791 00792 // 00793 // Remember to start the Fsp close thread if not currently started. 00794 // 00795 00796 if (!UdfData.FspCloseActive) { 00797 00798 UdfData.FspCloseActive = TRUE; 00799 StartWorker = TRUE; 00800 } 00801 00802 // 00803 // Unlock the global data. 00804 // 00805 00806 UdfUnlockUdfData(); 00807 } 00808 00809 // 00810 // Start the FspClose thread if we need to. 00811 // 00812 00813 if (StartWorker) { 00814 00815 ExQueueWorkItem( &UdfData.CloseItem, CriticalWorkQueue ); 00816 } 00817 00818 DebugTrace(( -1, Dbg, "UdfQueueClose -> VOID\n" )); 00819 00820 // 00821 // Return to our caller. 00822 // 00823 00824 return; 00825 } 00826 00827 00828 // 00829 // Local support routine 00830 // 00831 00832 PIRP_CONTEXT 00833 UdfRemoveClose ( 00834 IN PVCB Vcb OPTIONAL 00835 ) 00836 00837 /*++ 00838 00839 Routine Description: 00840 00841 Arguments: 00842 00843 This routine is called to scan the async and delayed close queues looking 00844 for a suitable entry. If the Vcb is specified then we scan both queues 00845 looking for an entry with the same Vcb. Otherwise we will look in the 00846 async queue first for any close item. If none found there then we look 00847 in the delayed close queue provided that we have triggered the delayed 00848 close operation. 00849 00850 Return Value: 00851 00852 PIRP_CONTEXT - NULL if no work item found. Otherwise it is the pointer to 00853 either the IrpContext or IrpContextLite for this request. 00854 00855 --*/ 00856 00857 { 00858 PIRP_CONTEXT IrpContext = NULL; 00859 PIRP_CONTEXT NextIrpContext; 00860 PIRP_CONTEXT_LITE NextIrpContextLite; 00861 00862 PLIST_ENTRY Entry; 00863 00864 PAGED_CODE(); 00865 00866 ASSERT_OPTIONAL_VCB( Vcb ); 00867 00868 // 00869 // Lock the UdfData to perform the scan. 00870 // 00871 00872 UdfLockUdfData(); 00873 00874 // 00875 // First check the list of async closes. 00876 // 00877 00878 Entry = UdfData.AsyncCloseQueue.Flink; 00879 00880 while (Entry != &UdfData.AsyncCloseQueue) { 00881 00882 // 00883 // Extract the IrpContext. 00884 // 00885 00886 NextIrpContext = CONTAINING_RECORD( Entry, 00887 IRP_CONTEXT, 00888 WorkQueueItem.List ); 00889 00890 // 00891 // If no Vcb was specified or this Vcb is for our volume 00892 // then perform the close. 00893 // 00894 00895 if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContext->Vcb == Vcb)) { 00896 00897 RemoveEntryList( Entry ); 00898 UdfData.AsyncCloseCount -= 1; 00899 00900 IrpContext = NextIrpContext; 00901 break; 00902 } 00903 00904 // 00905 // Move to the next entry. 00906 // 00907 00908 Entry = Entry->Flink; 00909 } 00910 00911 // 00912 // If we didn't find anything look through the delayed close 00913 // queue. 00914 // 00915 // We will only check the delayed close queue if we were given 00916 // a Vcb or the delayed close operation is active. 00917 // 00918 00919 if ((IrpContext == NULL) && 00920 (ARGUMENT_PRESENT( Vcb ) || 00921 (UdfData.ReduceDelayedClose && 00922 (UdfData.DelayedCloseCount > UdfData.MinDelayedCloseCount)))) { 00923 00924 Entry = UdfData.DelayedCloseQueue.Flink; 00925 00926 while (Entry != &UdfData.DelayedCloseQueue) { 00927 00928 // 00929 // Extract the IrpContext. 00930 // 00931 00932 NextIrpContextLite = CONTAINING_RECORD( Entry, 00933 IRP_CONTEXT_LITE, 00934 DelayedCloseLinks ); 00935 00936 // 00937 // If no Vcb was specified or this Vcb is for our volume 00938 // then perform the close. 00939 // 00940 00941 if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContextLite->Fcb->Vcb == Vcb)) { 00942 00943 RemoveEntryList( Entry ); 00944 UdfData.DelayedCloseCount -= 1; 00945 00946 IrpContext = (PIRP_CONTEXT) NextIrpContextLite; 00947 break; 00948 } 00949 00950 // 00951 // Move to the next entry. 00952 // 00953 00954 Entry = Entry->Flink; 00955 } 00956 } 00957 00958 // 00959 // If the Vcb wasn't specified and we couldn't find an entry 00960 // then turn off the Fsp thread. 00961 // 00962 00963 if (!ARGUMENT_PRESENT( Vcb ) && (IrpContext == NULL)) { 00964 00965 UdfData.FspCloseActive = FALSE; 00966 UdfData.ReduceDelayedClose = FALSE; 00967 } 00968 00969 // 00970 // Unlock the global data. 00971 // 00972 00973 UdfUnlockUdfData(); 00974 00975 return IrpContext; 00976 } 00977 00978

Generated on Sat May 15 19:39:25 2004 for test by doxygen 1.3.7