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

📄 write.c

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

            for (Fat = 0; Fat < (ULONG)Vcb->Bpb.Fats; Fat++) {

                IoRuns[Fat].Vbo = StartingDirtyVbo;
                IoRuns[Fat].Lbo = Fat * BytesPerFat + StartingDirtyVbo;
                IoRuns[Fat].Offset = StartingDirtyVbo - StartingVbo;
                IoRuns[Fat].ByteCount = WriteLength;
            }

            //
            //  Keep track of meta-data disk ios.
            //

            Vcb->Statistics[KeGetCurrentProcessorNumber()].Common.MetaDataDiskWrites += Vcb->Bpb.Fats;

            try {

                FatMultipleAsync( IrpContext,
                                  Vcb,
                                  Irp,
                                  (ULONG)Vcb->Bpb.Fats,
                                  IoRuns );

            } finally {

                if (IoRuns != StackIoRuns) {

                    ExFreePool( IoRuns );
                }
            }

            //
            //  Wait for all the writes to finish
            //

            FatWaitSync( IrpContext );

            //
            //  If we got an error, or verify required, remember it.
            //

            if (!NT_SUCCESS( Irp->IoStatus.Status )) {

                DebugTrace( 0,
                            Dbg,
                            "Error %X while writing volume file.\n",
                            Irp->IoStatus.Status );

                RaiseIosb = Irp->IoStatus;
            }
        }

        //
        //  If the writes were a success, set the sectors clean, else
        //  raise the error status and mark the volume as needing
        //  verification.  This will automatically reset the volume
        //  structures.
        //
        //  If not, then mark this volume as needing verification to
        //  automatically cause everything to get cleaned up.
        //

        Irp->IoStatus = RaiseIosb;

        if ( NT_SUCCESS( Status = Irp->IoStatus.Status )) {

            FatRemoveMcbEntry( Vcb, &Vcb->DirtyFatMcb,
                               StartingDirtyVbo,
                               WriteLength );

        } else {

            FatNormalizeAndRaiseStatus( IrpContext, Status );
        }

        DebugTrace(-1, Dbg, "CommonRead -> %08lx\n", Status );

        FatCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

    //
    //  This case corresponds to a general opened volume (DASD), ie.
    //  open ("a:").
    //

    if (TypeOfOpen == UserVolumeOpen) {

        LBO StartingLbo;
        LBO VolumeSize;

        //
        //  Precalculate the volume size since we're nearly always going
        //  to be wanting to use it.
        //

        VolumeSize = (LBO) Int32x32To64( Vcb->Bpb.BytesPerSector,
                                         (Vcb->Bpb.Sectors != 0 ? Vcb->Bpb.Sectors :
                                                                  Vcb->Bpb.LargeSectors));

        StartingLbo = StartingByte.QuadPart;

        DebugTrace(0, Dbg, "Type of write is User Volume.\n", 0);

        //
        //  Verify that the volume for this handle is still valid, permitting
        //  operations to proceed on dismounted volumes via the handle which
        //  performed the dismount.
        //

        if (!FlagOn( Ccb->Flags, CCB_FLAG_COMPLETE_DISMOUNT )) {

            FatQuickVerifyVcb( IrpContext, Vcb );
        }

        if (!FlagOn( Ccb->Flags, CCB_FLAG_DASD_PURGE_DONE )) {

            BOOLEAN PreviousWait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

            //
            //  Grab the entire volume so that even the normally unsafe action
            //  of writing to an unlocked volume won't open us to a race between
            //  the flush and purge of the FAT below.
            //
            //  I really don't think this is particularly important to worry about,
            //  but a repro case for another bug happens to dance into this race
            //  condition pretty easily. Eh.
            //
            
            SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
            FatAcquireExclusiveVolume( IrpContext, Vcb );

            try {

                //
                //  If the volume isn't locked, flush and purge it.
                //

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

                    FatFlushFat( IrpContext, Vcb );
                    CcPurgeCacheSection( &Vcb->SectionObjectPointers,
                                         NULL,
                                         0,
                                         FALSE );

                    FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
                }

            } finally {

                FatReleaseVolume( IrpContext, Vcb );
                if (!PreviousWait) {
                    ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
                }
            }

            SetFlag( Ccb->Flags, CCB_FLAG_DASD_PURGE_DONE |
                                 CCB_FLAG_DASD_FLUSH_DONE );
        }

        if (!FlagOn( Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO )) {

            //
            //  Make sure we don't try to write past end of volume,
            //  reducing the requested byte count if necessary.
            //

            if (WriteToEof || StartingLbo >= VolumeSize) {
                FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
                return STATUS_SUCCESS;
            }

            if (ByteCount > VolumeSize - StartingLbo) {

                ByteCount = (ULONG) (VolumeSize - StartingLbo);

                //
                //  For async writes we had set the byte count in the FatIoContext
                //  above, so fix that here.
                //

                if (!Wait) {

                    IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                        ByteCount;
                }
            }
        } else {

            //
            //  This has a peculiar interpretation, but just adjust the starting
            //  byte to the end of the visible volume.
            //

            if (WriteToEof) {

                StartingLbo = VolumeSize;
            }
        }

        //
        // For DASD we have to probe and lock the user's buffer
        //

        FatLockUserBuffer( IrpContext, Irp, IoReadAccess, ByteCount );

        //
        //  Set the FO_MODIFIED flag here to trigger a verify when this
        //  handle is closed.  Note that we can err on the conservative
        //  side with no problem, i.e. if we accidently do an extra
        //  verify there is no problem.
        //

        SetFlag( FileObject->Flags, FO_FILE_MODIFIED );

        //
        //  Write the data and wait for the results
        //

        FatSingleAsync( IrpContext,
                        Vcb,
                        StartingLbo,
                        ByteCount,
                        Irp );

        if (!Wait) {

            //
            //  We, nor anybody else, need the IrpContext any more.
            //

            IrpContext->FatIoContext = NULL;

            FatDeleteIrpContext( IrpContext );

            DebugTrace(-1, Dbg, "FatNonCachedIo -> STATUS_PENDING\n", 0);

            return STATUS_PENDING;
        }

        FatWaitSync( IrpContext );

        //
        //  If the call didn't succeed, raise the error status
        //
        //  Also mark this volume as needing verification to automatically
        //  cause everything to get cleaned up.
        //

        if (!NT_SUCCESS( Status = Irp->IoStatus.Status )) {

            FatNormalizeAndRaiseStatus( IrpContext, Status );
        }

        //
        //  Update the current file position.  We assume that
        //  open/create zeros out the CurrentByteOffset field.
        //

        if (SynchronousIo && !PagingIo) {
            FileObject->CurrentByteOffset.QuadPart =
                StartingLbo + Irp->IoStatus.Information;
        }

        DebugTrace(-1, Dbg, "FatCommonWrite -> %08lx\n", Status );

        FatCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

    //
    //  At this point we know there is an Fcb/Dcb.
    //

    ASSERT( FcbOrDcb != NULL );

    //
    //  Use a try-finally to free Fcb/Dcb and buffers on the way out.
    //

    try {

        //
        // This case corresponds to a normal user write file.
        //

        if ( TypeOfOpen == UserFileOpen ) {

            ULONG ValidDataLength;
            ULONG ValidDataToDisk;
            ULONG ValidDataToCheck;

            DebugTrace(0, Dbg, "Type of write is user file open\n", 0);

            //
            //  If this is a noncached transfer and is not a paging I/O, and
            //  the file has been opened cached, then we will do a flush here
            //  to avoid stale data problems.  Note that we must flush before
            //  acquiring the Fcb shared since the write may try to acquire
            //  it exclusive.
            //
            //  The Purge following the flush will garentee cache coherency.
            //

            if (NonCachedIo && !PagingIo &&
                (FileObject->SectionObjectPointer->DataSectionObject != NULL)) {

                //
                //  We need the Fcb exclsuive to do the CcPurgeCache
                //

                if (!FatAcquireExclusiveFcb( IrpContext, FcbOrDcb )) {

                    DebugTrace( 0, Dbg, "Cannot acquire FcbOrDcb = %08lx shared without waiting\n", FcbOrDcb );

                    try_return( PostIrp = TRUE );
                }

                FcbOrDcbAcquired = TRUE;
                FcbAcquiredExclusive = TRUE;

                //
                //  Preacquire pagingio for the flush.
                //
                
                ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );

                CcFlushCache( FileObject->SectionObjectPointer,
                              WriteToEof ? &FcbOrDcb->Header.FileSize : &StartingByte,
                              ByteCount,
                              &Irp->IoStatus );

                if (!NT_SUCCESS( Irp->IoStatus.Status )) {

                    ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
                    try_return( Irp->IoStatus.Status );
                }

                //
                //  Remember that we are holding the paging I/O resource.
                //

                PagingIoResourceAcquired = TRUE;

                //
                //  We hold so that we will prevent a pagefault from occuring and seeing
                //  soon-to-be stale data from the disk. We used to believe this was
                //  something to be left to the app to synchronize; we now realize that
                //  noncached IO on a fileserver is doomed without the filesystem forcing
                //  the coherency issue. By only penalizing noncached coherency when
                //  needed, this is about the best we can do.
                //
                
                CcPurgeCacheSection( FileObject->SectionObjectPointer,
                                     WriteToEof ? &FcbOrDcb->Header.FileSize : &StartingByte,
                                     ByteCount,
                                     FALSE );

                //
                //  Indicate we're OK with the fcb being demoted to shared access
                //  if that turns out to be possible later on after VDL extension
                //  is checked for.
                //
                //  PagingIo must be held all the way through.
                //
                
                FcbCanDemoteToShared = TRUE;
            }

            //
            //  We assert that Paging Io writes will never WriteToEof.
            //

⌨️ 快捷键说明

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