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

📄 write.c

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

                        UnwindOutstandingAsync = TRUE;

                        IrpContext->FatIoContext->Wait.Async.NonPagedFcb = FcbOrDcb->NonPaged;
                    }
                }

                //
                //  Now that we have the Fcb exclusive, get a new batch of
                //  filesize and ValidDataLength.
                //

                ValidDataToDisk = FcbOrDcb->ValidDataToDisk;
                ValidDataLength = FcbOrDcb->Header.ValidDataLength.LowPart;
                FileSize = FcbOrDcb->Header.FileSize.LowPart;

                //
                //  If this is PagingIo check again if any pruning is
                //  required.  It is important to start from basic
                //  princples in case the file was *grown* ...
                //

                if ( PagingIo ) {

                    if (StartingVbo >= FileSize) {
                        Irp->IoStatus.Information = 0;
                        try_return( Status = STATUS_SUCCESS );
                    }
                    
                    ByteCount = IrpSp->Parameters.Write.Length;

                    if (ByteCount > FileSize - StartingVbo) {
                        ByteCount = FileSize - StartingVbo;
                    }
                }
            }

            //
            //  Remember the final requested byte count
            //

            if (NonCachedIo && !Wait) {

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

            //
            //  Remember the initial file size and valid data length,
            //  just in case .....
            //

            InitialFileSize = FileSize;

            InitialValidDataLength = ValidDataLength;

            //
            //  Make sure the FcbOrDcb is still good
            //

            FatVerifyFcb( IrpContext, FcbOrDcb );

            //
            //  Check for writing to end of File.  If we are, then we have to
            //  recalculate a number of fields.
            //

            if ( WriteToEof ) {

                StartingVbo = FileSize;
                StartingByte = FcbOrDcb->Header.FileSize;

                //
                //  Since we couldn't know this information until now, perform the
                //  necessary bounds checking that we ommited at the top because
                //  this is a WriteToEof operation.
                //

                if (!FatIsIoRangeValid( Vcb, StartingByte, ByteCount )) {

                    Irp->IoStatus.Information = 0;
                    try_return( Status = STATUS_DISK_FULL );
                }
            }

            //
            //  If this is a non paging write to a data stream object we have to
            //  check for access according to the current state op/filelocks.
            //
            //  Note that after this point, operations will be performed on the file.
            //  No modifying activity can occur prior to this point in the write
            //  path.
            //

            if (!PagingIo && TypeOfOpen == UserFileOpen) {

                Status = FsRtlCheckOplock( &FcbOrDcb->Specific.Fcb.Oplock,
                                           Irp,
                                           IrpContext,
                                           FatOplockComplete,
                                           FatPrePostIrp );

                if (Status != STATUS_SUCCESS) {

                    OplockPostIrp = TRUE;
                    PostIrp = TRUE;
                    try_return( NOTHING );
                }

                //
                //  This oplock call can affect whether fast IO is possible.
                //  We may have broken an oplock to no oplock held.  If the
                //  current state of the file is FastIoIsNotPossible then
                //  recheck the fast IO state.
                //

                if (FcbOrDcb->Header.IsFastIoPossible == FastIoIsNotPossible) {

                    FcbOrDcb->Header.IsFastIoPossible = FatIsFastIoPossible( FcbOrDcb );
                }

                //
                //  And finally check the regular file locks.
                //

                if (!FsRtlCheckLockForWriteAccess( &FcbOrDcb->Specific.Fcb.FileLock, Irp )) {

                    try_return( Status = STATUS_FILE_LOCK_CONFLICT );
                }
            }

            //
            //  Determine if we will deal with extending the file. Note that
            //  this implies extending valid data, and so we already have all
            //  of the required synchronization done.
            //

            if (!PagingIo && (StartingVbo + ByteCount > FileSize)) {

                ExtendingFile = TRUE;
            }

            if ( ExtendingFile ) {

                //
                //  EXTENDING THE FILE
                //
                //  Update our local copy of FileSize
                //

                FileSize = StartingVbo + ByteCount;

                if (FcbOrDcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT) {

                    FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
                }

                //
                //  If the write goes beyond the allocation size, add some
                //  file allocation.
                //

                if ( FileSize > FcbOrDcb->Header.AllocationSize.LowPart ) {

                    BOOLEAN AllocateMinimumSize = TRUE;

                    //
                    //  Only do allocation chuncking on writes if this is
                    //  not the first allocation added to the file.
                    //

                    if (FcbOrDcb->Header.AllocationSize.LowPart != 0 ) {

                        ULONG ApproximateClusterCount;
                        ULONG TargetAllocation;
                        ULONG Multiplier;
                        ULONG BytesPerCluster;
                        ULONG ClusterAlignedFileSize;

                        //
                        //  We are going to try and allocate a bigger chunk than
                        //  we actually need in order to maximize FastIo usage.
                        //
                        //  The multiplier is computed as follows:
                        //
                        //
                        //            (FreeDiskSpace            )
                        //  Mult =  ( (-------------------------) / 32 ) + 1
                        //            (FileSize - AllocationSize)
                        //
                        //          and max out at 32.
                        //
                        //  With this formula we start winding down chunking
                        //  as we get near the disk space wall.
                        //
                        //  For instance on an empty 1 MEG floppy doing an 8K
                        //  write, the multiplier is 6, or 48K to allocate.
                        //  When this disk is half full, the multipler is 3,
                        //  and when it is 3/4 full, the mupltiplier is only 1.
                        //
                        //  On a larger disk, the multiplier for a 8K read will
                        //  reach its maximum of 32 when there is at least ~8 Megs
                        //  available.
                        //

                        //
                        //  Small write performance note, use cluster aligned
                        //  file size in above equation.
                        //

                        //
                        //  We need to carefully consider what happens when we approach
                        //  a 2^32 byte filesize.  Overflows will cause problems.
                        //

                        BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;

                        //
                        //  This can overflow if the target filesize is in the last cluster.
                        //  In this case, we can obviously skip over all of this fancy
                        //  logic and just max out the file right now.
                        //

                        ClusterAlignedFileSize = (FileSize + (BytesPerCluster - 1)) &
                                                 ~(BytesPerCluster - 1);

                        if (ClusterAlignedFileSize != 0) {

                            //
                            //  This actually has a chance but the possibility of overflowing
                            //  the numerator is pretty unlikely, made more unlikely by moving
                            //  the divide by 32 up to scale the BytesPerCluster. However, even if it does the
                            //  effect is completely benign.
                            //
                            //  FAT32 with a 64k cluster and over 2^21 clusters would do it (and
                            //  so forth - 2^(16 - 5 + 21) == 2^32).  Since this implies a partition
                            //  of 32gb and a number of clusters (and cluster size) we plan to
                            //  disallow in format for FAT32, the odds of this happening are pretty
                            //  low anyway.
                            //
    
                            Multiplier = ((Vcb->AllocationSupport.NumberOfFreeClusters *
                                           (BytesPerCluster >> 5)) /
                                          (ClusterAlignedFileSize -
                                           FcbOrDcb->Header.AllocationSize.LowPart)) + 1;
    
                            if (Multiplier > 32) { Multiplier = 32; }
    
                            Multiplier *= (ClusterAlignedFileSize - FcbOrDcb->Header.AllocationSize.LowPart);

                            TargetAllocation = FcbOrDcb->Header.AllocationSize.LowPart + Multiplier;
    
                            //
                            //  We know that TargetAllocation is in whole clusters, so simply
                            //  checking if it wrapped is correct.  If it did, we fall back
                            //  to allocating up to the maximum legal size.
                            //
    
                            if (TargetAllocation < FcbOrDcb->Header.AllocationSize.LowPart) {
    
                                TargetAllocation = ~BytesPerCluster + 1;
                                Multiplier = TargetAllocation - FcbOrDcb->Header.AllocationSize.LowPart;
                            }
    
                            //
                            //  Now do an unsafe check here to see if we should even
                            //  try to allocate this much.  If not, just allocate
                            //  the minimum size we need, if so so try it, but if it
                            //  fails, just allocate the minimum size we need.
                            //
    
                            ApproximateClusterCount = (Multiplier / BytesPerCluster);
    
                            if (ApproximateClusterCount <= Vcb->AllocationSupport.NumberOfFreeClusters) {
    
                                try {
    
                                    FatAddFileAllocation( IrpContext,
                                                          FcbOrDcb,
                                                          FileObject,
                                                          TargetAllocation );
    
                                    AllocateMinimumSize = FALSE;
                                    SetFlag( FcbOrDcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE );
    
                                } except( GetExceptionCode() == STATUS_DISK_FULL ?
                                          EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
    
                                      FatResetExceptionState( IrpContext );
                                }
                            }
                        }
                    }

                    if ( AllocateMinimumSize ) {

                        FatAddFileAllocation( IrpContext,
                                              FcbOrDcb,
                                              FileObject,
                                              FileSize );
                    }

                    //
                    //  Assert that the allocation worked
                    //

                    ASSERT( FcbOrDcb->Header.AllocationSize.LowPart >= FileSize );
                }

                //
                //  Set the new file size in the Fcb
                //

                ASSERT( FileSize <= FcbOrDcb->Header.AllocationSize.LowPart );

                FcbOrDcb->Header.FileSize.LowPart = FileSize;

                //
                //  Extend the cache map, letting mm knows the new file size.
                //  We only have to do this if the file is cached.
                //

                if (CcIsFileCached(FileObject)) {
                    CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&FcbOrDcb->Header.AllocationSize );
                }
            }

            //
            //  Determine if we will deal with extending valid data.
            //

            if ( !CalledByLazyWriter &&
                 !RecursiveWriteThrough &&
                 (StartingVbo + ByteCount > ValidDataLength) ) {

                ExtendingValidData = TRUE;
            
            } else {

                //
                //  If not extending valid data, and we otherwise believe we
                //  could demote from exclusive to shared, do so.  This will
                //  occur when we synchronize tight for noncached coherency
                //  but must defer the demotion until after we decide about
                //  valid data length, which requires it exclusive.  Since we
                //  can't drop/re-pick the resources without letting a pagefault
                //  squirt through, the resource decision was kept up in the air
                //  until now.
                //
                //  Note that we've still got PagingIo exclusive in these cases.
                //
                
                if (FcbCanDemoteToShared) {

                    ASSERT( FcbAcquiredExclusive && ExIsResourceAcquiredExclusiveLite( FcbOrDcb->Header.Resource ));
                    ExConvertExclusiveToSharedLite( FcbOrDcb->Header.Resource );
                    FcbAcquiredExclusive = FALSE;
                }
            }
            
            if (ValidDataToDisk > ValidDataLength) {
                
                ValidDataToCheck = ValidDataToDisk;
            
            } else {
                
                ValidDataToCheck = ValidDataLength;
            }

            //
            // HANDLE THE NON-CACHED CASE
            //

⌨️ 快捷键说明

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