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

📄 flush.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 3 页
字号:
    return Status;
}


NTSTATUS
FatFlushDirectory (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB Dcb,
    IN FAT_FLUSH_TYPE FlushType
    )

/*++

Routine Description:

    This routine non-recursively flushes a dcb tree.

Arguments:

    Dcb - Supplies the Dcb being flushed

    FlushType - Specifies the kind of flushing to perform
    
Return Value:

    VOID

--*/

{
    PFCB Fcb;
    PVCB Vcb;
    PFCB NextFcb;

    PDIRENT Dirent;
    PBCB DirentBcb = NULL;

    NTSTATUS Status;
    NTSTATUS ReturnStatus = STATUS_SUCCESS;

    BOOLEAN ClearWriteThroughOnExit = FALSE;
    BOOLEAN ClearWaitOnExit = FALSE;

    PAGED_CODE();

    ASSERT( FatVcbAcquiredExclusive(IrpContext, Dcb->Vcb) );

    DebugTrace(+1, Dbg, "FatFlushDirectory, Dcb = %08lx\n", Dcb);

    //
    //  First flush all the files, then the directories, to make sure all the
    //  file sizes and times get sets correctly on disk.
    //
    //  We also have to check here if the "Ea Data. Sf" fcb really
    //  corressponds to an existing file.
    //

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

        ClearWriteThroughOnExit = TRUE;
        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
    }

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

        ClearWaitOnExit = TRUE;
        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    }

    Vcb = Dcb->Vcb;
    Fcb = Dcb;

    while (Fcb != NULL) {

        NextFcb = FatGetNextFcbTopDown(IrpContext, Fcb, Dcb);

        if ( (NodeType( Fcb ) == FAT_NTC_FCB) &&
             (Vcb->EaFcb != Fcb) &&
             !IsFileDeleted(IrpContext, Fcb)) {

            (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );

            ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

            //
            //  Exception handler to catch and commute errors encountered
            //  doing the flush dance.  We may encounter corruption, and
            //  should continue flushing the volume as much as possible.
            //
            
            try {
                
                //
                //  Standard handler to release resources, etc.
                //
                
                try {
    
                    //
                    //  Make sure the Fcb is OK.
                    //
    
                    try {
    
                        FatVerifyFcb( IrpContext, Fcb );
    
                    } except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
                              EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
    
                        FatResetExceptionState( IrpContext );
                    }
    
                    //
                    //  If this Fcb is not good skip it.  Note that a 'continue'
                    //  here would be very expensive as we inside a try{} body.
                    //
    
                    if (Fcb->FcbCondition != FcbGood) {
    
                        try_leave( NOTHING);
                    }
    
                    //
                    //  In case a handle was never closed and the FS and AS are more
                    //  than a cluster different, do this truncate.
                    //
    
                    if ( FlagOn(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE) ) {
    
                        FatTruncateFileAllocation( IrpContext,
                                                   Fcb,
                                                   Fcb->Header.FileSize.LowPart );
                    }
    
                    //
                    //  Also compare the file's dirent in the parent directory
                    //  with the size information in the Fcb and update
                    //  it if neccessary.  Note that we don't mark the Bcb dirty
                    //  because we will be flushing the file object presently, and
                    //  Mm knows what's really dirty.
                    //
    
                    FatGetDirentFromFcbOrDcb( IrpContext,
                                              Fcb,
                                              FALSE,
                                              &Dirent,
                                              &DirentBcb );
    
                    if (Dirent->FileSize != Fcb->Header.FileSize.LowPart) {
    
                        Dirent->FileSize = Fcb->Header.FileSize.LowPart;
                    }
    
                    //
                    //  We must unpin the Bcb before the flush since we recursively tear up
                    //  the tree if Mm decides that the data section is no longer referenced
                    //  and the final close comes in for this file. If this parent has no
                    //  more children as a result, we will try to initiate teardown on it
                    //  and Cc will deadlock against the active count of this Bcb.
                    //
    
                    FatUnpinBcb( IrpContext, DirentBcb );
                    
                    //
                    //  Now flush the file.  Note that this may make the Fcb
                    //  go away if Mm dereferences its file object.
                    //
    
                    Status = FatFlushFile( IrpContext, Fcb, FlushType );
    
                    if (!NT_SUCCESS(Status)) {
    
                        ReturnStatus = Status;
                    }
    
                } finally {
    
                    FatUnpinBcb( IrpContext, DirentBcb );
    
                    //
                    //  Since we have the Vcb exclusive we know that if any closes
                    //  come in it is because the CcPurgeCacheSection caused the
                    //  Fcb to go away.
                    //
    
                    if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB) ) {
    
                        FatReleaseFcb( (IRPCONTEXT), Fcb );
                    }
                }
             
            } except( (ReturnStatus = FsRtlIsNtstatusExpected(GetExceptionCode())) ?
                       EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {

                   FatResetExceptionState( IrpContext );
             }
        }

        Fcb = NextFcb;
    }

    //
    //  OK, now flush the directories.
    //

    Fcb = Dcb;

    while (Fcb != NULL) {

        NextFcb = FatGetNextFcbTopDown(IrpContext, Fcb, Dcb);

        if ( (NodeType( Fcb ) != FAT_NTC_FCB) &&
             !IsFileDeleted(IrpContext, Fcb) ) {

            //
            //  Make sure the Fcb is OK.
            //

            try {

                FatVerifyFcb( IrpContext, Fcb );

            } except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
                      EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {

                FatResetExceptionState( IrpContext );
            }

            if (Fcb->FcbCondition == FcbGood) {

                Status = FatFlushFile( IrpContext, Fcb, FlushType );

                if (!NT_SUCCESS(Status)) {

                    ReturnStatus = Status;
                }
            }
        }

        Fcb = NextFcb;
    }

    try {

        FatUnpinRepinnedBcbs( IrpContext );

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

        ReturnStatus = IrpContext->ExceptionStatus;
    }

    if (ClearWriteThroughOnExit) {

        ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
    }
    if (ClearWaitOnExit) {

        ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    }

    DebugTrace(-1, Dbg, "FatFlushDirectory -> 0x%08lx\n", ReturnStatus);

    return ReturnStatus;
}


NTSTATUS
FatFlushFat (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb
    )

/*++

Routine Description:

    The function carefully flushes the entire FAT for a volume.  It is
    nessecary to dance around a bit because of complicated synchronization
    reasons.

Arguments:

    Vcb - Supplies the Vcb whose FAT is being flushed
    
Return Value:

    VOID

--*/

{
    PBCB Bcb;
    PVOID DontCare;
    IO_STATUS_BLOCK Iosb;
    LARGE_INTEGER Offset;

    NTSTATUS ReturnStatus = STATUS_SUCCESS;

    PAGED_CODE();

    //
    //  If this volume is write protected, no need to flush.
    //

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

        return STATUS_SUCCESS;
    }

    //
    //  Make sure the Vcb is OK.
    //

    try {

        FatVerifyVcb( IrpContext, Vcb );

    } except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
              EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {

        FatResetExceptionState( IrpContext );
    }

    if (Vcb->VcbCondition != VcbGood) {

        return STATUS_FILE_INVALID;
    }

    //
    //  The only way we have to correctly synchronize things is to
    //  repin stuff, and then unpin repin it.
    //
    //  With NT 5.0, we can use some new cache manager support to make
    //  this a lot more efficient (important for FAT32).  Since we're
    //  only worried about ranges that are dirty - and since we're a
    //  modified-no-write stream - we can assume that if there is no
    //  BCB, there is no work to do in the range. I.e., the lazy writer
    //  beat us to it.
    //
    //  This is much better than reading the entire FAT in and trying
    //  to punch it out (see the test in the write path to blow
    //  off writes that don't correspond to dirty ranges of the FAT).
    //  For FAT32, this would be a *lot* of reading.
    //

    if (Vcb->AllocationSupport.FatIndexBitSize != 12) {

        //
        //  Walk through the Fat, one page at a time.
        //

        ULONG NumberOfPages;
        ULONG Page;

        NumberOfPages = ( FatReservedBytes(&Vcb->Bpb) +
                          FatBytesPerFat(&Vcb->Bpb) +
                          (PAGE_SIZE - 1) ) / PAGE_SIZE;


        for ( Page = 0, Offset.QuadPart = 0;
              Page < NumberOfPages;
              Page++, Offset.LowPart += PAGE_SIZE ) {

            try {

                if (CcPinRead( Vcb->VirtualVolumeFile,
                               &Offset,
                               PAGE_SIZE,
                               PIN_WAIT | PIN_IF_BCB,
                               &Bcb,
                               &DontCare )) {
                    
                    CcSetDirtyPinnedData( Bcb, NULL );
                    CcRepinBcb( Bcb );
                    CcUnpinData( Bcb );
                    CcUnpinRepinnedBcb( Bcb, TRUE, &Iosb );

                    if (!NT_SUCCESS(Iosb.Status)) {

                        ReturnStatus = Iosb.Status;
                    }
                }

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

                ReturnStatus = IrpContext->ExceptionStatus;
                continue;
            }
        }

    } else {

        //
        //  We read in the entire fat in the 12 bit case.
        //

        Offset.QuadPart = FatReservedBytes( &Vcb->Bpb );

        try {

            if (CcPinRead( Vcb->VirtualVolumeFile,
                           &Offset,
                           FatBytesPerFat( &Vcb->Bpb ),
                           PIN_WAIT | PIN_IF_BCB,
                           &Bcb,
                           &DontCare )) {
                
                CcSetDirtyPinnedData( Bcb, NULL );
                CcRepinBcb( Bcb );
                CcUnpinData( Bcb );
                CcUnpinRepinnedBcb( Bcb, TRUE, &Iosb );

                if (!NT_SUCCESS(Iosb.Status)) {

                    ReturnStatus = Iosb.Status;
                }
            }

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

⌨️ 快捷键说明

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