⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cachesup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:
                              (PCC_FILE_SIZES)&Dcb->Header.AllocationSize,
                              TRUE,
                              &FatData.CacheManagerNoOpCallbacks,
                              Dcb );
    }

    DebugTrace(-1, Dbg, "FatOpenDirectoryFile -> VOID\n", 0);

    return;
}


PFILE_OBJECT
FatOpenEaFile (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB EaFcb
    )

/*++

Routine Description:

    This routine opens the Ea file.

Arguments:

    EaFcb - Pointer to the Fcb for the Ea file.

Return Value:

    Pointer to the new file object.

--*/

{
    PFILE_OBJECT EaFileObject = NULL;
    PDEVICE_OBJECT RealDevice;

    PAGED_CODE();
    
    DebugTrace(+1, Dbg, "FatOpenEaFile\n", 0);
    DebugTrace( 0, Dbg, "EaFcb = %08lx\n", EaFcb);

    //
    //  Create the special file object for the ea file, and set
    //  up its pointers back to the Fcb and the section object pointer
    //

    RealDevice = EaFcb->Vcb->CurrentDevice;

    EaFileObject = IoCreateStreamFileObject( NULL, RealDevice );

    try {

        FatPreallocateCloseContext( IrpContext->Vcb);

        FatSetFileObject( EaFileObject,
                          EaFile,
                          EaFcb,
                          NULL );

        //
        //  Remember this internal, residual open.
        //

        InterlockedIncrement( &(EaFcb->Vcb->InternalOpenCount) );
        InterlockedIncrement( &(EaFcb->Vcb->ResidualOpenCount) );

        EaFileObject->SectionObjectPointer = &EaFcb->NonPaged->SectionObjectPointers;

        EaFileObject->ReadAccess = TRUE;
        EaFileObject->WriteAccess = TRUE;

        //
        //  Finally check if we need to initialize the Cache Map for the
        //  ea file.  The size of the section we are going to map
        //  the current allocation size for the Fcb.
        //

        EaFcb->Header.ValidDataLength = FatMaxLarge;

        CcInitializeCacheMap( EaFileObject,
                              (PCC_FILE_SIZES)&EaFcb->Header.AllocationSize,
                              TRUE,
                              &FatData.CacheManagerCallbacks,
                              EaFcb );

        CcSetAdditionalCacheAttributes( EaFileObject, TRUE, TRUE );
    
    } finally {

        //
        //  Drop the fileobject if we're raising.  Two cases: couldn't get
        //  the close context, and it is still an UnopenedFileObject, or
        //  we lost trying to build the cache map - in which case we're
        //  OK for the close context if we have to.
        //
        
        if (AbnormalTermination()) {
            
            ObDereferenceObject( EaFileObject );
        }
    }

    DebugTrace(-1, Dbg, "FatOpenEaFile -> %08lx\n", EaFileObject);

    UNREFERENCED_PARAMETER( IrpContext );

    return EaFileObject;
}


VOID
FatCloseEaFile (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN BOOLEAN FlushFirst
    )

/*++

Routine Description:

    This routine shuts down the ea file.  Usually this is required when the volume
    begins to leave the system: after verify, dismount, deletion, pnp.
    
Arguments:

    Vcb - the volume to close the ea file on
    
    FlushFirst - whether the file should be flushed
    
Return Value:

    None. As a side effect, the EA fileobject in the Vcb is cleared.
    
    Caller must have the Vcb exclusive.
    
--*/

{
    PFILE_OBJECT EaFileObject = Vcb->VirtualEaFile;

    PAGED_CODE();
    
    DebugTrace(+1, Dbg, "FatCloseEaFile\n", 0);
    DebugTrace( 0, Dbg, "Vcb = %08lx\n", Vcb);

    ASSERT( FatVcbAcquiredExclusive(IrpContext, Vcb) );

    if (EaFileObject != NULL) {

        EaFileObject = Vcb->VirtualEaFile;

        if (FlushFirst) {

            CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );
        }

        Vcb->VirtualEaFile = NULL;

        //
        //  Empty the Mcb for the Ea file.
        //

        FatRemoveMcbEntry( Vcb, &Vcb->EaFcb->Mcb, 0, 0xFFFFFFFF );

        //
        //  Uninitialize the cache for this file object and dereference it.
        //

        FatSyncUninitializeCacheMap( IrpContext, EaFileObject );

        ObDereferenceObject( EaFileObject );
    }
    
    DebugTrace(-1, Dbg, "FatCloseEaFile -> %08lx\n", EaFileObject);
}


VOID
FatSetDirtyBcb (
    IN PIRP_CONTEXT IrpContext,
    IN PBCB Bcb,
    IN PVCB Vcb OPTIONAL,
    IN BOOLEAN Reversible
    )

/*++

Routine Description:

    This routine saves a reference to the bcb in the irp context and
    sets the bcb dirty.  This will have the affect of keeping the page in
    memory until we complete the request

    In addition, a DPC is set to fire in 5 seconds (or if one is pending,
    pushed back 5 seconds) to mark the volume clean.

Arguments:

    Bcb - Supplies the Bcb being set dirty
    
    Vcb - Supplies the volume being marked dirty
    
    Reversible - Supplies TRUE if the specified range of bcb should be repinned
        so that the changes can be reversed in a controlled fashion if errors
        are encountered.
    
Return Value:

    None.

--*/

{
    DebugTrace(+1, Dbg, "FatSetDirtyBcb\n", 0 );
    DebugTrace( 0, Dbg, "IrpContext = %08lx\n", IrpContext );
    DebugTrace( 0, Dbg, "Bcb        = %08lx\n", Bcb );
    DebugTrace( 0, Dbg, "Vcb        = %08lx\n", Vcb );

    //
    //  Repin the bcb as required
    //

    if (Reversible) {
    
        FatRepinBcb( IrpContext, Bcb );
    }

    //
    //  Set the bcb dirty
    //

    CcSetDirtyPinnedData( Bcb, NULL );

    //
    //  If volume dirtying isn't disabled for this operation (for
    //  instance, when we're changing the dirty state), set the
    //  volume dirty if we were given a Vcb that we want to perform
    //  clean volume processing on, and return.
    //
    //  As a historical note, we used to key off of the old floppy
    //  (now deferred flush) bit to disable dirtying behavior.  Since
    //  hotpluggable media can still be yanked while operations are
    //  in flight, recognize that its really the case that FAT12
    //  doesn't have the dirty bit.
    //

    if ( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_DIRTY) &&
         ARGUMENT_PRESENT(Vcb) &&
         !FatIsFat12(Vcb)) {

        KIRQL SavedIrql;

        BOOLEAN SetTimer;

        LARGE_INTEGER TimeSincePreviousCall;
        LARGE_INTEGER CurrentTime;

        //
        //  "Borrow" the irp context spinlock.
        //

        KeQuerySystemTime( &CurrentTime );

        KeAcquireSpinLock( &FatData.GeneralSpinLock, &SavedIrql );

        TimeSincePreviousCall.QuadPart =
                CurrentTime.QuadPart - Vcb->LastFatMarkVolumeDirtyCall.QuadPart;

        //
        //  If more than one second has elapsed since the prior call
        //  to here, bump the timer up again and see if we need to
        //  physically mark the volume dirty.
        //

        if ( (TimeSincePreviousCall.HighPart != 0) ||
             (TimeSincePreviousCall.LowPart > (1000 * 1000 * 10)) ) {

            SetTimer = TRUE;

        } else {

            SetTimer = FALSE;
        }

        KeReleaseSpinLock( &FatData.GeneralSpinLock, SavedIrql );

        if ( SetTimer ) {

            LARGE_INTEGER CleanVolumeTimer;

            //
            //  We use a shorter volume clean timer for hot plug volumes.
            //
            
            CleanVolumeTimer.QuadPart = FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH)
                                           ? (LONG)-1500*1000*10
                                           : (LONG)-8*1000*1000*10;

            (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
            (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );

            //
            //  We have now synchronized with anybody clearing the dirty
            //  flag, so we can now see if we really have to actually write
            //  out the physical bit.
            //

            if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY) ) {

                //
                //  We want to really mark the volume dirty now.
                //

                if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {

                    FatMarkVolume( IrpContext, Vcb, VolumeDirty );
                }

                SetFlag( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );

                //
                //  Lock the volume if it is removable.
                //

                if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA)) {

                    FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
                }
            }

            KeAcquireSpinLock( &FatData.GeneralSpinLock, &SavedIrql );

            KeQuerySystemTime( &Vcb->LastFatMarkVolumeDirtyCall );

            KeReleaseSpinLock( &FatData.GeneralSpinLock, SavedIrql );

            KeSetTimer( &Vcb->CleanVolumeTimer,
                        CleanVolumeTimer,
                        &Vcb->CleanVolumeDpc );
        }
    }

    DebugTrace(-1, Dbg, "FatSetDirtyBcb -> VOID\n", 0 );
}


VOID
FatRepinBcb (
    IN PIRP_CONTEXT IrpContext,
    IN PBCB Bcb
    )

/*++

Routine Description:

    This routine saves a reference to the bcb in the irp context. This will
    have the affect of keeping the page in memory until we complete the
    request

Arguments:

    Bcb - Supplies the Bcb being referenced

Return Value:

    None.

--*/

{
    PREPINNED_BCBS Repinned;
    ULONG i;

    PAGED_CODE();
    
    DebugTrace(+1, Dbg, "FatRepinBcb\n", 0 );
    DebugTrace( 0, Dbg, "IrpContext = %08lx\n", IrpContext );
    DebugTrace( 0, Dbg, "Bcb        = %08lx\n", Bcb );

    //
    //  The algorithm is to search the list of repinned records until
    //  we either find a match for the bcb or we find a null slot.
    //

    Repinned = &IrpContext->Repinned;

    while (TRUE) {

        //
        //  For every entry in the repinned record check if the bcb's
        //  match or if the entry is null.  If the bcb's match then
        //  we've done because we've already repinned this bcb, if
        //  the entry is null then we know, because it's densely packed,
        //  that the bcb is not in the list so add it to the repinned
        //  record and repin it.
        //

        for (i = 0; i < REPINNED_BCBS_ARRAY_SIZE; i += 1) {

            if (Repinned->Bcb[i] == Bcb) {

                DebugTrace(-1, Dbg, "FatRepinBcb -> VOID\n", 0 );
                return;
            }

            if (Repinned->Bcb[i] == NULL) {

                Repinned->Bcb[i] = Bcb;
                CcRepinBcb( Bcb );

                DebugTrace(-1, Dbg, "FatRepinBcb -> VOID\n", 0 );
                return;
            }
        }

        //
        //  We finished checking one repinned record so now locate the next
        //  repinned record,  If there isn't one then allocate and zero out
        //  a new one.
        //

        if (Repinned->Next == NULL) {

            Repinned->Next = FsRtlAllocatePoolWithTag( PagedPool,
                                                       sizeof(REPINNED_BCBS),
                                                       TAG_REPINNED_BCB );

            RtlZeroMemory( Repinned->Next, sizeof(REPINNED_BCBS) );
        }

        Repinned = Repinned->Next;
    }
}


VOID
FatUnpinRepinnedBcbs (
    IN PIRP_CONTEXT IrpContext
    )

/*++

Routine Description:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -