/* This routine performs Close operation for all files from Delayed Close queue. */ VOID UDFCloseAllDelayed( IN PVCB Vcb ) { PLIST_ENTRY Entry; PtrUDFIrpContextLite NextIrpContextLite; BOOLEAN GlobalDataAcquired = FALSE; AdPrint((" UDFCloseAllDelayed\n")); // Acquire DelayedCloseResource if (!ExIsResourceAcquiredExclusive(&UDFGlobalData.GlobalDataResource)) { UDFAcquireResourceExclusive(&(UDFGlobalData.DelayedCloseResource), TRUE); GlobalDataAcquired = TRUE; } Entry = UDFGlobalData.DelayedCloseQueue.Flink; while (Entry != &UDFGlobalData.DelayedCloseQueue) { // Extract the IrpContext. NextIrpContextLite = CONTAINING_RECORD( Entry, UDFIrpContextLite, DelayedCloseLinks ); Entry = Entry->Flink; if (NextIrpContextLite->Fcb->Vcb == Vcb) { RemoveEntryList( &(NextIrpContextLite->DelayedCloseLinks) ); UDFGlobalData.DelayedCloseCount--; UDFDoDelayedClose(NextIrpContextLite); } } Entry = UDFGlobalData.DirDelayedCloseQueue.Flink; while (Entry != &UDFGlobalData.DirDelayedCloseQueue) { // Extract the IrpContext. NextIrpContextLite = CONTAINING_RECORD( Entry, UDFIrpContextLite, DelayedCloseLinks ); Entry = Entry->Flink; if (NextIrpContextLite->Fcb->Vcb == Vcb) { RemoveEntryList( &(NextIrpContextLite->DelayedCloseLinks) ); UDFGlobalData.DirDelayedCloseCount--; UDFDoDelayedClose(NextIrpContextLite); } } // Release DelayedCloseResource if(GlobalDataAcquired) UDFReleaseResource(&(UDFGlobalData.DelayedCloseResource)); } // end UDFCloseAllDelayed()
VOID SrvCloseEndpoint ( IN PENDPOINT Endpoint ) /*++ Routine Description: This function closes a transport endpoint. *** This function must be called with SrvEndpointLock held exactly once. The lock is released on exit. Arguments: Endpoint - Supplies a pointer to an Endpoint Block Return Value: None. --*/ { CSHORT index; PCONNECTION connection; PAGED_CODE( ); ASSERT( ExIsResourceAcquiredExclusive(&RESOURCE_OF(SrvEndpointLock)) ); if ( GET_BLOCK_STATE(Endpoint) == BlockStateActive ) { IF_DEBUG(BLOCK1) SrvPrint1( "Closing endpoint at %lx\n", Endpoint ); SET_BLOCK_STATE( Endpoint, BlockStateClosing ); // // Close all active connections. // index = (CSHORT)-1; while ( TRUE ) { // // Get the next active connection in the table. If no more // are available, WalkConnectionTable returns NULL. // Otherwise, it returns a referenced pointer to a // connection. // connection = WalkConnectionTable( Endpoint, &index ); if ( connection == NULL ) { break; } // // We don't want to hold the endpoint lock while we close the // connection (this causes lock level problems). Since we // already have a referenced pointer to the connection, this // is safe. // RELEASE_LOCK( &SrvEndpointLock ); #if SRVDBG29 UpdateConnectionHistory( "CEND", Endpoint, connection ); #endif SrvCloseConnection( connection, FALSE ); ACQUIRE_LOCK( &SrvEndpointLock ); SrvDereferenceConnection( connection ); } // // Close all free connections. // EmptyFreeConnectionList( Endpoint ); // // We don't need to hold the endpoint lock anymore. // RELEASE_LOCK( &SrvEndpointLock ); // // Close the endpoint file handle. This causes all pending // requests to be aborted. It also deregisters all event // handlers. // // *** Note that we have a separate reference to the file // object, in addition to the handle. We don't release that // reference until all activity on the endpoint has ceased // (in SrvDereferenceEndpoint). // SRVDBG_RELEASE_HANDLE( Endpoint->EndpointHandle, "END", 2, Endpoint ); SrvNtClose( Endpoint->EndpointHandle, FALSE ); if ( Endpoint->IsConnectionless ) { SRVDBG_RELEASE_HANDLE( Endpoint->NameSocketHandle, "END", 2, Endpoint ); SrvNtClose( Endpoint->NameSocketHandle, FALSE ); } // // Dereference the endpoint (to indicate that it's no longer // open). // SrvDereferenceEndpoint( Endpoint ); INCREMENT_DEBUG_STAT( SrvDbgStatistics.EndpointInfo.Closes ); } else { RELEASE_LOCK( &SrvEndpointLock ); } return; } // SrvCloseEndpoint
VOID NtfsReleaseVcbCheckDelete ( IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN UCHAR MajorCode, IN PFILE_OBJECT FileObject OPTIONAL ) /*++ Routine Description: This routine will release the Vcb. We will also test here whether we should teardown the Vcb at this point. If this is the last open queued to a dismounted volume or the last close from a failed mount or the failed mount then we will want to test the Vcb for a teardown. Arguments: Vcb - Supplies the Vcb to acquire MajorCode - Indicates what type of operation we were called from. FileObject - Optionally supplies the file object whose VPB pointer we need to zero out Return Value: None. --*/ { ASSERT_IRP_CONTEXT(IrpContext); ASSERT_VCB(Vcb); if (FlagOn( Vcb->VcbState, VCB_STATE_PERFORMED_DISMOUNT ) && (Vcb->CloseCount == 0)) { ULONG ReferenceCount; ULONG ResidualCount; KIRQL SavedIrql; BOOLEAN DeleteVcb = FALSE; ASSERT_EXCLUSIVE_RESOURCE( &Vcb->Resource ); // // The volume has gone through dismount. Now we need to decide if this // release of the Vcb is the last reference for this volume. If so we // can tear the volume down. // // We compare the reference count in the Vpb with the state of the volume // and the type of operation. We also need to check if there is a // referenced log file object. // IoAcquireVpbSpinLock( &SavedIrql ); ReferenceCount = Vcb->Vpb->ReferenceCount; IoReleaseVpbSpinLock( SavedIrql ); ResidualCount = 0; if (Vcb->LogFileObject != NULL) { ResidualCount = 1; } if (MajorCode == IRP_MJ_CREATE) { ResidualCount += 1; } // // If the residual count is the same as the count in the Vpb then we // can delete the Vpb. // if (ResidualCount == ReferenceCount) { SetFlag( Vcb->VcbState, VCB_STATE_DELETE_UNDERWAY ); ExReleaseResource( &Vcb->Resource ); // // Never delete the Vcb unless this is the last release of // this Vcb. // if (!ExIsResourceAcquiredExclusive( &Vcb->Resource ) && (ExIsResourceAcquiredShared( &Vcb->Resource ) == 0)) { if (ARGUMENT_PRESENT(FileObject)) { FileObject->Vpb = NULL; } // // If this is a create then the IO system will handle the // Vpb. // if (MajorCode == IRP_MJ_CREATE) { ClearFlag( Vcb->VcbState, VCB_STATE_TEMP_VPB ); } // // Use the global resource to synchronize the DeleteVcb process. // (VOID) ExAcquireResourceExclusive( &NtfsData.Resource, TRUE ); RemoveEntryList( &Vcb->VcbLinks ); ExReleaseResource( &NtfsData.Resource ); NtfsDeleteVcb( IrpContext, &Vcb ); } else { ClearFlag( Vcb->VcbState, VCB_STATE_DELETE_UNDERWAY ); } } else { ExReleaseResource( &Vcb->Resource ); } } else { ExReleaseResource( &Vcb->Resource ); } }