Пример #1
0
NTSTATUS
FatFsdCleanup (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of closing down a handle to a
    file object.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Cleanup exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

#if __NDAS_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = FILE_OPENED;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    //
    //  If we were called with our file system device object instead of a
    //  volume device object, just complete this request with STATUS_SUCCESS
    //

    if ( FatDeviceIsFatFsdo( VolumeDeviceObject))  {

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = FILE_OPENED;

        IoCompleteRequest( Irp, IO_DISK_INCREMENT );

        return STATUS_SUCCESS;
    }

    DebugTrace(+1, Dbg, "FatFsdCleanup\n", 0);

    //
    //  Call the common Cleanup routine, with blocking allowed.
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#if (__NDAS_FAT_PRIMARY__ || __NDAS_FAT_SECONDARY__)

	do {
	
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, TRUE );
				IrpContext->TopLevel = TopLevel;

#if __NDAS_FAT_PRIMARY__
			{
				ULONG_PTR				stackBottom;
				ULONG_PTR				stackTop;
			    BOOLEAN					validPrimaryRequest = FALSE;
				PPRIMARY_REQUEST_INFO	primaryRequestInfo;
				PIO_STACK_LOCATION		irpSp = IoGetCurrentIrpStackLocation( Irp );
    
				primaryRequestInfo = (PPRIMARY_REQUEST_INFO)IoGetTopLevelIrp();
			    IoGetStackLimits( &stackTop, &stackBottom );

			    if ( (ULONG_PTR)primaryRequestInfo <= stackBottom - sizeof(PRIMARY_REQUEST_INFO)	&&
					 (ULONG_PTR) primaryRequestInfo >= stackTop										&&
					 (!FlagOn( (ULONG_PTR) primaryRequestInfo, 0x3 ))								&&
					 primaryRequestInfo->PrimaryTag == 0xe2027482) {										

					validPrimaryRequest = TRUE;
				}
					
				if (validPrimaryRequest) {
						
					//ASSERT( FatIsTopLevelRequest(IrpContext) );

					IoSetTopLevelIrp( NULL );
					TopLevel = FatIsIrpTopLevel( Irp );
					ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL );

					if (IsListEmpty(&VolumeDeviceObject->PrimarySessionQueue)) {

						NDAS_ASSERT( FALSE );
					}

					IrpContext->PrimaryRequestInfo = *primaryRequestInfo;

					DebugTrace2( 0, Dbg, ("primaryRequestInfo = %p\n", primaryRequestInfo) );
				}
			} 
#endif
			}

#if __NDAS_FAT_SECONDARY__

			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

				Status = STATUS_SUCCESS;

				while (TRUE) {
										
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {
		
						if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

						if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}

						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );
						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonCleanup( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
					}
				}

			} else
				Status = FatCommonCleanup( IrpContext, Irp );
#else
	        Status = FatCommonCleanup( IrpContext, Irp );
#endif

	    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

		    //
			//  We had some trouble trying to perform the requested
	        //  operation, so we'll abort the I/O request with
		    //  the error status that we get back from the
			//  execption code
			//

	        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}

	} while (Status == STATUS_CANT_WAIT);
Пример #2
0
VOID
SecondaryTryClose(
	IN PIRP_CONTEXT	IrpContext2  OPTIONAL,
	IN PSECONDARY	Secondary
	)
{
	IRP_CONTEXT			irpContext;

	BOOLEAN				secondaryResourceAcquired = FALSE;
	BOOLEAN				acquiredVcb = FALSE;
	BOOLEAN				wait;

	PFCB				fcb;
	BOOLEAN				acquiredFcb = FALSE;
	BOOLEAN				removedFcb;
	PFCB				nextFcb = NULL;
	PVOID				restartKey;
	PLIST_ENTRY			deletedFcbListEntry;


	DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles start\n") );

	try {

		RtlZeroMemory( &irpContext, sizeof(IRP_CONTEXT) );
		SetFlag( irpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
		SetFlag( irpContext.NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		irpContext.Vcb = &Secondary->VolDo->Vcb;

		secondaryResourceAcquired = SecondaryAcquireResourceSharedLite( &irpContext, 
																		&Secondary->Resource, 
																		FALSE );
		if (secondaryResourceAcquired == FALSE)
			leave;
		
		wait = BooleanFlagOn( irpContext.Flags, IRP_CONTEXT_FLAG_WAIT );

		acquiredVcb = FatAcquireExclusiveSecondaryVcb( &irpContext, irpContext.Vcb );

		if (acquiredVcb == FALSE)
			leave;

		SetFlag( Secondary->VolDo->Vcb.NdFatFlags, ND_FAT_VCB_FLAG_TRY_CLOSE_FILES );
		FatFspClose( &Secondary->VolDo->Vcb );
		ClearFlag( Secondary->VolDo->Vcb.NdFatFlags, ND_FAT_VCB_FLAG_TRY_CLOSE_FILES );

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles FatFspClose, Secondary->VolDo->Vcb.SecondaryOpenCount = %d\n", 
							    Secondary->VolDo->Vcb.SecondaryOpenFileCount) );

		SetFlag( irpContext.NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		Secondary_TryCloseFilExts( Secondary );

	} finally {

		ASSERT( nextFcb == NULL );

		ClearFlag( irpContext.NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		if (acquiredVcb)
			FatReleaseSecondaryVcb( &irpContext, irpContext.Vcb );
		
		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles exit\n") );

		ExAcquireFastMutex( &Secondary->FastMutex );		
		Secondary->TryCloseActive = FALSE;
		ExReleaseFastMutex( &Secondary->FastMutex );

		if (secondaryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->Resource );

		Secondary_Dereference( Secondary );
	}

	return;
}
Пример #3
0
NTSTATUS
NtfsFsdLockControl (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Lock Control.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;

    NTSTATUS Status = STATUS_SUCCESS;
    PIRP_CONTEXT IrpContext = NULL;

#if __NDAS_NTFS__

	if ((PVOID)NdasNtfsControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    ASSERT_IRP( Irp );

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsFsdLockControl\n") );

    //
    //  Call the common Lock Control routine
    //

    FsRtlEnterFileSystem();

    ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, FALSE, FALSE );

    do {

        try {

            //
            //  We are either initiating this request or retrying it.
            //

            if (IrpContext == NULL) {

                //
                //  Allocate and initialize the Irp.
                //

                NtfsInitializeIrpContext( Irp, CanFsdWait( Irp ), &IrpContext );

                //
                //  Initialize the thread top level structure, if needed.
                //
    
                NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );

            } else if (Status == STATUS_LOG_FILE_FULL) {

                NtfsCheckpointForLogFileFull( IrpContext );
            }

#if __NDAS_NTFS_SECONDARY__

			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( NtfsIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
				SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_FILE );

				Status = STATUS_SUCCESS;

				for (;;) {
										
					NDAS_ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					NDAS_ASSERT( secondaryResourceAcquired == FALSE );

					if (!FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT)) {

						Status = NtfsPostRequest( IrpContext, Irp );
						break;
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
						
						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Resource, 
																	 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Resource, 
															  BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );

					NDAS_ASSERT( secondaryResourceAcquired == TRUE );

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = NtfsCommonLockControl( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
					}
				}

			} else
				Status = NtfsCommonLockControl( IrpContext, Irp );
#else
            Status = NtfsCommonLockControl( IrpContext, Irp );
#endif
            break;

        } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {

            //
            //  We had some trouble trying to perform the requested
            //  operation, so we'll abort the I/O request with
            //  the error status that we get back from the
            //  execption code
            //

            Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
        }

    } while (Status == STATUS_CANT_WAIT ||
Пример #4
0
NTSTATUS
NtfsFsdPnp (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD entry point for plug and play (Pnp).

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;

    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;

    PIRP_CONTEXT IrpContext = NULL;

#if __NDAS_NTFS__

	if ((PVOID)NdasNtfsControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    ASSERT_IRP( Irp );

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

#ifdef NTFSPNPDBG
    if (NtfsDebugTraceLevel != 0) SetFlag( NtfsDebugTraceLevel, DEBUG_TRACE_PNP );
#endif

    DebugTrace( +1, Dbg, ("NtfsFsdPnp\n") );

    //
    //  Call the common Pnp routine
    //

    FsRtlEnterFileSystem();

    switch( IoGetCurrentIrpStackLocation( Irp )->MinorFunction ) {

    case IRP_MN_QUERY_REMOVE_DEVICE:
    case IRP_MN_REMOVE_DEVICE:
    case IRP_MN_CANCEL_REMOVE_DEVICE:
    case IRP_MN_SURPRISE_REMOVAL:
    
        ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, FALSE, FALSE );
        break;
        
    default:
        
        ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, TRUE, TRUE );
        break;
    }
    
    do {

        try {

            //
            //  We are either initiating this request or retrying it.
            //

            if (IrpContext == NULL) {

                //
                //  Allocate and initialize the Irp.
                //

                NtfsInitializeIrpContext( Irp, TRUE, &IrpContext );

                //
                //  Initialize the thread top level structure, if needed.
                //
    
                NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );

            } else if (Status == STATUS_LOG_FILE_FULL) {

                NtfsCheckpointForLogFileFull( IrpContext );
            }

#if __NDAS_NTFS_SECONDARY__

			if (!FlagOn(VolumeDeviceObject->NetdiskPartitionInformation.Flags, NETDISK_PARTITION_INFORMATION_FLAG_INDIRECT) &&
				VolumeDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY) {

				if ((IrpContext->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE	|| 
					 IrpContext->MinorFunction == IRP_MN_SURPRISE_REMOVAL		||
					 IrpContext->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)) {

					BOOLEAN	secondaryResourceAcquired = FALSE;
					BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

					ASSERT( NtfsIsTopLevelRequest(IrpContext) );

					Status = STATUS_SUCCESS;

					for (;;) {
										
						NDAS_ASSERT( secondaryRecoveryResourceAcquired == FALSE );
						NDAS_ASSERT( secondaryResourceAcquired == FALSE );

						if (!FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT)) {

							Status = NtfsPostRequest( IrpContext, Irp );
							break;
						}
					
						if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
						
							secondaryRecoveryResourceAcquired 
								= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																		 &VolumeDeviceObject->RecoveryResource, 
																		 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );
								
							if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

								SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
								secondaryRecoveryResourceAcquired = FALSE;
								continue;
							}

							secondaryResourceAcquired 
								= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																		 &VolumeDeviceObject->Resource, 
																		 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );
							try {
								
								SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
							} finally {

								SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
								secondaryResourceAcquired = FALSE;

								SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
								secondaryRecoveryResourceAcquired = FALSE;
							}

							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceSharedLite( IrpContext, 
																  &VolumeDeviceObject->Resource, 
																  BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );

						NDAS_ASSERT( secondaryResourceAcquired == TRUE );

						break;
					}

					if (Status == STATUS_SUCCESS) {
					
						try {

							if (VolumeDeviceObject->NetdiskEnableMode != NETDISK_SECONDARY) {

								NDAS_ASSERT( VolumeDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY );
								NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );
							}
							
							SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

							Status = NtfsCommonPnp( IrpContext, &Irp );
							
						} finally {

							ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
							SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
						}
					}
				
				} else {

					if (VolumeDeviceObject->NetdiskEnableMode != NETDISK_SECONDARY) {

						NDAS_ASSERT( VolumeDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY );
						NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );
					}

					SetFlag( IrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

					Status = NtfsCommonPnp( IrpContext, &Irp );
				}

			} else {

				Status = NtfsCommonPnp( IrpContext, &Irp );
			}
#else
            Status = NtfsCommonPnp( IrpContext, &Irp );
#endif
            break;

        } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
Пример #5
0
NTSTATUS
FatFsdFlushBuffers (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Flush buffers.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being flushed exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "FatFsdFlushBuffers\n", 0);

    //
    //  Call the common Cleanup routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#ifdef __ND_FAT__

	do {
    
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, CanFsdWait(Irp) );
				IrpContext->TopLevel = TopLevel;
			}

#ifdef __ND_FAT_SECONDARY__

			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

#ifdef __ND_FAT_DBG__
				ASSERT( FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_FILE) );
#endif				

				Status = STATUS_SUCCESS;

				while (TRUE) {
			
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) || 
						FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {
		
						if(!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
						
						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Secondary->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Secondary->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SessionRecovery( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Secondary->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );

						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonFlushBuffers( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Secondary->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->Resource );
					}
				}

			} else
				Status = FatCommonFlushBuffers( IrpContext, Irp );
#else
	        Status = FatCommonFlushBuffers( IrpContext, Irp );
#endif
            break;

		} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

			//
	        //  We had some trouble trying to perform the requested
		    //  operation, so we'll abort the I/O request with
			//  the error status that we get back from the
	        //  execption code
		    //

			Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}
	
	} while (Status == STATUS_CANT_WAIT);
Пример #6
0
VOID
SecondaryTryClose (
	IN PSECONDARY	Secondary
	)
{
	PIRP_CONTEXT	irpContext;

	BOOLEAN			secondaryResourceAcquired = FALSE;
	BOOLEAN			acquiredVcb = FALSE;
	BOOLEAN			wait;

	irpContext = FatAllocateIrpContext();

	if (irpContext == NULL) {

		return;
	}

	DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles start\n") );

	try {

		RtlZeroMemory( irpContext, sizeof(IRP_CONTEXT) );
		SetFlag( irpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
		SetFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		irpContext->Vcb = &Secondary->VolDo->Vcb;

		secondaryResourceAcquired = SecondaryAcquireResourceSharedLite( irpContext, 
																		&Secondary->VolDo->Resource, 
																		FALSE );
		if (secondaryResourceAcquired == FALSE) {

			leave;
		}

		wait = BooleanFlagOn( irpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

		acquiredVcb = FatAcquireExclusiveVcb( irpContext, irpContext->Vcb );

		if (acquiredVcb == FALSE) {

			leave;
		}

		FsRtlEnterFileSystem();
		FatFspClose( &Secondary->VolDo->Vcb );
		FsRtlExitFileSystem();

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles FatFspClose, Secondary->VolDo->Vcb.SecondaryOpenCount = %d\n", 
							    Secondary->VolDo->Vcb.SecondaryOpenFileCount) );

		SetFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		Secondary_TryCloseFilExts( Secondary );

	} finally {

		ClearFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		if (acquiredVcb) {

			FatReleaseVcb( irpContext, irpContext->Vcb );
		}

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles exit\n") );

		ExAcquireFastMutex( &Secondary->FastMutex );		
		Secondary->TryCloseActive = FALSE;
		ExReleaseFastMutex( &Secondary->FastMutex );

		if (secondaryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->Resource );

		Secondary_Dereference(Secondary);

		FatFreeIrpContext(irpContext);
	}

	return;
}
Пример #7
0
VOID
FatFspDispatch (
    IN PVOID Context
    )

/*++

Routine Description:

    This is the main FSP thread routine that is executed to receive
    and dispatch IRP requests.  Each FSP thread begins its execution here.
    There is one thread created at system initialization time and subsequent
    threads created as needed.

Arguments:


    Context - Supplies the thread id.

Return Value:

    None - This routine never exits

--*/

{
    NTSTATUS Status;

    PIRP Irp;
    PIRP_CONTEXT IrpContext;
    PIO_STACK_LOCATION IrpSp;
    BOOLEAN VcbDeleted;

    PVOLUME_DEVICE_OBJECT VolDo;

    PAGED_CODE();

    IrpContext = (PIRP_CONTEXT)Context;

    Irp = IrpContext->OriginatingIrp;

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Now because we are the Fsp we will force the IrpContext to
    //  indicate true on Wait.
    //

    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT | IRP_CONTEXT_FLAG_IN_FSP);

    //
    //  If this request has an associated volume device object, remember it.
    //

    if ( IrpSp->FileObject != NULL ) {

        VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
                                   VOLUME_DEVICE_OBJECT,
                                   DeviceObject );
    } else {

        VolDo = NULL;
    }

    //
    //  Now case on the function code.  For each major function code,
    //  either call the appropriate FSP routine or case on the minor
    //  function and then call the FSP routine.  The FSP routine that
    //  we call is responsible for completing the IRP, and not us.
    //  That way the routine can complete the IRP and then continue
    //  post processing as required.  For example, a read can be
    //  satisfied right away and then read can be done.
    //
    //  We'll do all of the work within an exception handler that
    //  will be invoked if ever some underlying operation gets into
    //  trouble (e.g., if FatReadSectorsSync has trouble).
    //

    while ( TRUE ) {

        DebugTrace(0, Dbg, "FatFspDispatch: Irp = 0x%08lx\n", Irp);

        //
        //  If this Irp was top level, note it in our thread local storage.
        //

        FsRtlEnterFileSystem();

        if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) ) {

            IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );

        } else {

            IoSetTopLevelIrp( Irp );
        }

#if __NDAS_FAT__

		do {

#if __NDAS_FAT_SECONDARY__

			BOOLEAN	volDoResourceAcquired = FALSE;

#endif

			try {

#if __NDAS_FAT_SECONDARY__

				Status = STATUS_SUCCESS;

				if (Irp && IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

					BOOLEAN volDoRecoveryResourceAcquired = FALSE;

					ASSERT( FatIsTopLevelRequest(IrpContext) );

					ASSERT( FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT) );

					while (TRUE) {
			
						ASSERT( volDoRecoveryResourceAcquired == FALSE );
						ASSERT( volDoResourceAcquired == FALSE );

						if (FlagOn(VolDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
		
							volDoRecoveryResourceAcquired 
								= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																		 &VolDo->Secondary->RecoveryResource, 
																		 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
							if (!FlagOn(VolDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

								SecondaryReleaseResourceLite( IrpContext, &VolDo->Secondary->RecoveryResource );
								volDoRecoveryResourceAcquired = FALSE;
								continue;
							}

							volDoResourceAcquired 
								= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																		 &VolDo->Secondary->Resource, 
																		 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
							try {
								
								SecondaryRecoverySessionStart( VolDo->Secondary, IrpContext );
								
							} finally {

								SecondaryReleaseResourceLite( IrpContext, &VolDo->Secondary->Resource );
								volDoResourceAcquired = FALSE;

								SecondaryReleaseResourceLite( IrpContext, &VolDo->Secondary->RecoveryResource );
								volDoRecoveryResourceAcquired = FALSE;
							}

							continue;
						}

						volDoResourceAcquired 
							= SecondaryAcquireResourceSharedLite( IrpContext, 
																  &VolDo->Secondary->Resource, 
																  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

						ASSERT( volDoResourceAcquired == TRUE );

						break;
					}
				}
#endif

	            switch ( IrpContext->MajorFunction ) {

		            //
			        //  For Create Operation,
				    //

					case IRP_MJ_CREATE:

						(VOID) FatCommonCreate( IrpContext, Irp );
	                    break;

		            //
			        //  For close operations.  We do a little kludge here in case
				    //  this close causes a volume to go away.  It will NULL the
					//  VolDo local variable so that we will not try to look at
	                //  the overflow queue.
		            //

	                case IRP_MJ_CLOSE:

		            {
			            PVCB Vcb;
				        PFCB Fcb;
					    PCCB Ccb;
						TYPE_OF_OPEN TypeOfOpen;

	                    //
		                //  Extract and decode the file object
			            //

				        TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );

					    //
						//  Do the close.  We have a slightly different format
	                    //  for this call because of the async closes.
		                //

			            Status = FatCommonClose( Vcb,
				                                 Fcb,
					                             Ccb,
						                         TypeOfOpen,
							                     TRUE,
								                 &VcbDeleted );

	                    //
		                //  If the VCB was deleted, do not try to access it later.
			            //

				        if (VcbDeleted) {

					        VolDo = NULL;
						}

	                    ASSERT(Status == STATUS_SUCCESS);

		                FatCompleteRequest( IrpContext, Irp, Status );

			            break;
				    }

	                //
		            //  For read operations
			        //

				    case IRP_MJ_READ:

					    (VOID) FatCommonRead( IrpContext, Irp );
						break;

	                //
		            //  For write operations,
			        //

				    case IRP_MJ_WRITE:

					    (VOID) FatCommonWrite( IrpContext, Irp );
						break;

	                //
		            //  For Query Information operations,
			        //

				    case IRP_MJ_QUERY_INFORMATION:

					    (VOID) FatCommonQueryInformation( IrpContext, Irp );
						break;

	                //
		            //  For Set Information operations,
			        //

				    case IRP_MJ_SET_INFORMATION:

					    (VOID) FatCommonSetInformation( IrpContext, Irp );
						break;

	                //
		            //  For Query EA operations,
			        //

				    case IRP_MJ_QUERY_EA:

					    (VOID) FatCommonQueryEa( IrpContext, Irp );
						break;

	                //
		            //  For Set EA operations,
			        //

				    case IRP_MJ_SET_EA:

					    (VOID) FatCommonSetEa( IrpContext, Irp );
						break;

	                //
		            //  For Flush buffers operations,
			        //

				    case IRP_MJ_FLUSH_BUFFERS:

					    (VOID) FatCommonFlushBuffers( IrpContext, Irp );
						break;

	                //
		            //  For Query Volume Information operations,
			        //

				    case IRP_MJ_QUERY_VOLUME_INFORMATION:

					    (VOID) FatCommonQueryVolumeInfo( IrpContext, Irp );
						break;

	                //
		            //  For Set Volume Information operations,
			        //

				    case IRP_MJ_SET_VOLUME_INFORMATION:

					    (VOID) FatCommonSetVolumeInfo( IrpContext, Irp );
						break;

	                //
		            //  For File Cleanup operations,
			        //

				    case IRP_MJ_CLEANUP:

					    (VOID) FatCommonCleanup( IrpContext, Irp );
						break;

	                //
		            //  For Directory Control operations,
			        //

				    case IRP_MJ_DIRECTORY_CONTROL:

					    (VOID) FatCommonDirectoryControl( IrpContext, Irp );
						break;

	                //
		            //  For File System Control operations,
			        //

				    case IRP_MJ_FILE_SYSTEM_CONTROL:

					    (VOID) FatCommonFileSystemControl( IrpContext, Irp );
						break;

	                //
		            //  For Lock Control operations,
			        //

				    case IRP_MJ_LOCK_CONTROL:

					    (VOID) FatCommonLockControl( IrpContext, Irp );
						break;

	                //
		            //  For Device Control operations,
			        //

				    case IRP_MJ_DEVICE_CONTROL:

					    (VOID) FatCommonDeviceControl( IrpContext, Irp );
						break;

	                //
		            //  For the Shutdown operation,
			        //

				    case IRP_MJ_SHUTDOWN:

					    (VOID) FatCommonShutdown( IrpContext, Irp );
						break;

	                //
		            //  For plug and play operations.
			        //

				    case IRP_MJ_PNP:

					    //
						//  I don't believe this should ever occur, but allow for the unexpected.
	                    //

		                (VOID) FatCommonPnp( IrpContext, Irp );
			            break;

				    //
					//  For any other major operations, return an invalid
	                //  request.
		            //

			        default:

				        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
					    break;

				}

#if __NDAS_FAT_SECONDARY__

				if (volDoResourceAcquired) {

					SecondaryReleaseResourceLite( NULL, &VolDo->Secondary->Resource );
					volDoResourceAcquired = FALSE;
				}
#endif


	        } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

#if __NDAS_FAT_SECONDARY__

				if (volDoResourceAcquired) {

					SecondaryReleaseResourceLite( NULL, &VolDo->Secondary->Resource );
					volDoResourceAcquired = FALSE;
				}
#endif
				
				//
			    //  We had some trouble trying to perform the requested
				//  operation, so we'll abort the I/O request with
	            //  the error status that we get back from the
		        //  execption code.
			    //

				Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
			}
		
		} while (Status == STATUS_CANT_WAIT);
Пример #8
0
NTSTATUS
FatFsdQueryVolumeInformation (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the Fsd part of the NtQueryVolumeInformation API
    call.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the file
        being queried exists.

    Irp - Supplies the Irp being processed.

Return Value:

    NTSTATUS - The FSD status for the Irp.

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

#if __NDAS_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    DebugTrace(+1, Dbg, "FatFsdQueryVolumeInformation\n", 0);

    //
    //  Call the common query routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#if (__NDAS_FAT_PRIMARY__ || __NDAS_FAT_SECONDARY__)

	do {
    
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, CanFsdWait(Irp) );
				IrpContext->TopLevel = TopLevel;
			}

#if __NDAS_FAT_SECONDARY__

			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				BOOLEAN	volDoResourceAcquired = FALSE;
				BOOLEAN volDoRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

				Status = STATUS_SUCCESS;

				for (;;) {
			
					NDAS_ASSERT( volDoRecoveryResourceAcquired == FALSE );
					NDAS_ASSERT( volDoResourceAcquired == FALSE );

					if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

						Status = FatFsdPostRequest( IrpContext, Irp );
						break;
					}
									
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

						volDoRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							volDoRecoveryResourceAcquired = FALSE;
							continue;
						}

						volDoResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
							volDoResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							volDoRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					volDoResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					NDAS_ASSERT( volDoResourceAcquired == TRUE );

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
					}
				}

			} else
				Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
#else
	        Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
#endif
            break;

		} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

			//
	        //  We had some trouble trying to perform the requested
		    //  operation, so we'll abort the I/O request with
			//  the error status that we get back from the
	        //  execption code
		    //

			Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}
	
	} while (Status == STATUS_CANT_WAIT);
Пример #9
0
VOID
FatFspClose (
    IN PVCB Vcb OPTIONAL
    )

/*++

Routine Description:

    This routine implements the FSP part of Close.

Arguments:

    Vcb - If present, tells us to only close file objects opened on the
        specified volume.

Return Value:

    None.

--*/

{
    PCLOSE_CONTEXT CloseContext;
    PVCB CurrentVcb = NULL;
    PVCB LastVcb = NULL;
    BOOLEAN FreeContext;

    ULONG LoopsWithVcbHeld;
    
    DebugTrace(+1, Dbg, "FatFspClose\n", 0);

    //
    //  Set the top level IRP for the true FSP operation.
    //
    
    if (!ARGUMENT_PRESENT( Vcb )) {
        
        IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
    }
    
    while (CloseContext = FatRemoveClose(Vcb, LastVcb)) {

#ifdef __ND_FAT_SECONDARY__
		NTSTATUS	Status;
#endif

        //
        //  If we are in the FSP (i.e. Vcb == NULL), then try to keep ahead of
        //  creates by doing several closes with one acquisition of the Vcb.
        //
        //  Note that we cannot be holding the Vcb on entry to FatCommonClose
        //  if this is last close as we will try to acquire FatData, and
        //  worse the volume (and therefore the Vcb) may go away.
        //

        if (!ARGUMENT_PRESENT(Vcb)) {
             
            if (!FatData.ShutdownStarted) {

                if (CloseContext->Vcb != CurrentVcb) {

                    LoopsWithVcbHeld = 0;

                    //
                    //  Release a previously held Vcb, if any.
                    //

                    if (CurrentVcb != NULL) {

                        ExReleaseResourceLite( &CurrentVcb->Resource);
                    }

                    //
                    //  Get the new Vcb.
                    //

                    CurrentVcb = CloseContext->Vcb;
                    (VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );

                } else {

                    //
                    //  Share the resource occasionally if we seem to be finding a lot
                    //  of closes for a single volume.
                    //

                    if (++LoopsWithVcbHeld >= 20) {

                        if (ExGetSharedWaiterCount( &CurrentVcb->Resource ) +
                            ExGetExclusiveWaiterCount( &CurrentVcb->Resource )) {

                            ExReleaseResourceLite( &CurrentVcb->Resource);
                            (VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );
                        }

                        LoopsWithVcbHeld = 0;
                    }
                }

                //
                //  Now check the Open count.  We may be about to delete this volume!
                //
                //  The test below must be <= 1 because there could still be outstanding
                //  stream references on this VCB that are not counted in the OpenFileCount.
                //  For example if there are no open files OpenFileCount could be zero and we would
                //  not release the resource here.  The call to FatCommonClose() below may cause
                //  the VCB to be torn down and we will try to release memory we don't
                //  own later.
                //

                if (CurrentVcb->OpenFileCount <= 1) {

                    ExReleaseResourceLite( &CurrentVcb->Resource);
                    CurrentVcb = NULL;
                }
            //
            //  If shutdown has started while processing our list, drop the
            //  current Vcb resource.
            //

            } else if (CurrentVcb != NULL) {

                ExReleaseResourceLite( &CurrentVcb->Resource);
                CurrentVcb = NULL;
            }
        }

        LastVcb = CurrentVcb;

        //
        //  Call the common Close routine.  Protected in a try {} except {}
        //

        try {

            //
            //  The close context either is in the CCB, automatically freed,
            //  or was from pool for a metadata fileobject, CCB is NULL, and
            //  we'll need to free it.
            //

            FreeContext = CloseContext->Free;

#ifdef __ND_FAT_SECONDARY__

			if (CloseContext->Fcb && FlagOn(CloseContext->Fcb->NdFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) {

				PVOLUME_DEVICE_OBJECT VolumeDeviceObject = (CONTAINING_RECORD(CloseContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb));

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FreeContext == FALSE );

				Status = STATUS_SUCCESS;

				while (TRUE) {
			
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
		
						if (FlagOn(VolumeDeviceObject->Vcb.NdFatFlags, ND_FAT_VCB_FLAG_TRY_CLOSE_FILES)) {
								
							Status = STATUS_CANT_WAIT;
							break;
						}

						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( NULL, 
																	 &VolumeDeviceObject->Secondary->RecoveryResource, 
																	 TRUE );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( NULL, 
																	 &VolumeDeviceObject->Secondary->Resource, 
																	 TRUE );
						try {
								
							SessionRecovery( VolumeDeviceObject->Secondary, NULL );
								
						} finally {

							SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( NULL, 
															  &VolumeDeviceObject->Secondary->Resource, 
															  TRUE );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) ); 
							
						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {
	
						Status = FatCommonClose( CloseContext->Vcb,
												 CloseContext->Fcb,
												 (FreeContext ? NULL :
																CONTAINING_RECORD( CloseContext, CCB, CloseContext)),
												 CloseContext->TypeOfOpen,
												 TRUE,
												 NULL );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Secondary->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->Resource );
					}
				}

			} else
				Status = FatCommonClose( CloseContext->Vcb,
										 CloseContext->Fcb,
										 (FreeContext ? NULL :
														CONTAINING_RECORD( CloseContext, CCB, CloseContext)),
										 CloseContext->TypeOfOpen,
										 TRUE,
										 NULL );
#else
            (VOID)FatCommonClose( CloseContext->Vcb,
                                  CloseContext->Fcb,
                                  (FreeContext ? NULL :
                                                 CONTAINING_RECORD( CloseContext, CCB, CloseContext)),
                                  CloseContext->TypeOfOpen,
                                  TRUE,
                                  NULL );
#endif

        } except(FatExceptionFilter( NULL, GetExceptionInformation() )) {

            //
            //  Ignore anything we expect.
            //

              NOTHING;
        }

        //
        //  Drop the context if it came from pool.
        //
        
#ifdef __ND_FAT_SECONDARY__

		if (Status == STATUS_CANT_WAIT) {

			ASSERT( FreeContext == FALSE );

			ASSERT( CloseContext->Fcb && FlagOn(CloseContext->Fcb->FcbState, FCB_STATE_DELAY_CLOSE) );

            FatQueueClose( CloseContext, 
                           (BOOLEAN)(CloseContext->Fcb && FlagOn(CloseContext->Fcb->FcbState, FCB_STATE_DELAY_CLOSE)) );
			break;
		}

		if (FreeContext) {

			ExFreePool( CloseContext );
		}

#else

        if (FreeContext) {

            ExFreePool( CloseContext );
        }

#endif
    }