Beispiel #1
0
NTSTATUS
Ext2ReadComplete (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS        Status = STATUS_UNSUCCESSFUL;
    PFILE_OBJECT    FileObject;
    PIRP            Irp;

    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        FileObject = IrpContext->FileObject;
        Irp = IrpContext->Irp;

        CcMdlReadComplete(FileObject, Irp->MdlAddress);
        Irp->MdlAddress = NULL;
        Status = STATUS_SUCCESS;

    } __finally {

        if (!IrpContext->ExceptionInProgress) {
            Ext2CompleteIrpContext(IrpContext, Status);
        }
    }

    return Status;
}
Beispiel #2
0
NTSTATUS
NtfsCompleteMdl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the function of completing Mdl read and write
    requests.  It should be called only from NtfsFsdRead and NtfsFsdWrite.

Arguments:

    Irp - Supplies the originating Irp.

Return Value:

    NTSTATUS - Will always be STATUS_PENDING or STATUS_SUCCESS.

--*/

{
    PFILE_OBJECT FileObject;
    PIO_STACK_LOCATION IrpSp;
    PNTFS_ADVANCED_FCB_HEADER Header;

    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsCompleteMdl\n") );
    DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp        = %08lx\n", Irp) );

    //
    // Do completion processing.
    //

    FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;

    switch( IrpContext->MajorFunction ) {

    case IRP_MJ_READ:

        CcMdlReadComplete( FileObject, Irp->MdlAddress );
        break;

    case IRP_MJ_WRITE:

        try {

            PSCB Scb;
            VBO StartingVbo;
            LONGLONG ByteCount;
            LONGLONG ByteRange;
            BOOLEAN DoingIoAtEof = FALSE;

            ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ));

            IrpSp = IoGetCurrentIrpStackLocation( Irp );
            Scb = (PSCB)(IrpSp->FileObject->FsContext);
            Header = &(Scb->Header);

            //
            //  Now synchronize with the FsRtl Header and Scb.
            //

            if (Header->PagingIoResource != NULL) {

                StartingVbo = IrpSp->Parameters.Write.ByteOffset.QuadPart;
                ByteCount = (LONGLONG) IrpSp->Parameters.Write.Length;
                ByteRange = StartingVbo + ByteCount + PAGE_SIZE - 1;
                ClearFlag( ((ULONG) ByteRange), PAGE_SIZE - 1 );

                ExAcquireResourceSharedLite( Header->PagingIoResource, TRUE );
                NtfsAcquireFsrtlHeader( Scb );

                //
                //  Now see if this is at EOF.
                //  Recursive flush will generate IO which ends on page boundary
                //  which is why we rounded the range
                //

                if (ByteRange > Header->ValidDataLength.QuadPart) {

                    //
                    //  Mark that we are writing to EOF.  If someone else is currently
                    //  writing to EOF, wait for them.
                    //

                    ASSERT( ByteRange - StartingVbo < MAXULONG );

                    DoingIoAtEof = !FlagOn( Header->Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE ) ||
                                   NtfsWaitForIoAtEof( Header, (PLARGE_INTEGER)&StartingVbo, (ULONG)(ByteRange - StartingVbo) );

                    if (DoingIoAtEof) {

                        SetFlag( Header->Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE );

#if (DBG || defined( NTFS_FREE_ASSERTS ))
                        ((PSCB) Header)->IoAtEofThread = (PERESOURCE_THREAD) ExGetCurrentResourceThread();
#endif
                        //
                        //  Store this in the IrpContext until commit or post.
                        //

                        IrpContext->CleanupStructure = Scb;
                    }
                }

                NtfsReleaseFsrtlHeader( Scb );
            }

            CcMdlWriteComplete( FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress );

        } finally {

            if (Header->PagingIoResource != NULL) {

                ExReleaseResourceLite( Header->PagingIoResource );
            }
        }

        break;

    default:

        DebugTrace( DEBUG_TRACE_ERROR, 0, ("Illegal Mdl Complete.\n") );

        ASSERTMSG("Illegal Mdl Complete, About to bugcheck ", FALSE);
        NtfsBugCheck( IrpContext->MajorFunction, 0, 0 );
    }

    //
    // Mdl is now deallocated.
    //

    Irp->MdlAddress = NULL;

    //
    //  Ignore errors.  CC has already cleaned up his structures.
    //

    IrpContext->ExceptionStatus = STATUS_SUCCESS;
    NtfsMinimumExceptionProcessing( IrpContext );

    //
    // Complete the request and exit right away.
    //

    NtfsCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );

    DebugTrace( -1, Dbg, ("NtfsCompleteMdl -> STATUS_SUCCESS\n") );

    return STATUS_SUCCESS;
}
Beispiel #3
0
NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
    UINT8* data;
    PFILE_OBJECT FileObject = IrpSp->FileObject;
    fcb* fcb = FileObject->FsContext;
    UINT64 start;
    ULONG length, bytes_read;
    NTSTATUS Status;
    BOOL top_level;
    
    FsRtlEnterFileSystem();
    
    top_level = is_top_level(Irp);
    
    TRACE("read\n");
    
    Irp->IoStatus.Information = 0;
    
    if (IrpSp->MinorFunction & IRP_MN_COMPLETE) {
        CcMdlReadComplete(IrpSp->FileObject, Irp->MdlAddress);
        
        Irp->MdlAddress = NULL;
        Status = STATUS_SUCCESS;
        bytes_read = 0;
        
        goto exit;
    }
    
    start = IrpSp->Parameters.Read.ByteOffset.QuadPart;
    length = IrpSp->Parameters.Read.Length;
    bytes_read = 0;
    
    if (!fcb || !fcb->Vcb || !fcb->subvol) {
        Status = STATUS_INTERNAL_ERROR; // FIXME - invalid param error?
        goto exit;
    }
    
    TRACE("file = %S (fcb = %p)\n", file_desc(FileObject), fcb);
    TRACE("offset = %llx, length = %x\n", start, length);
    TRACE("paging_io = %s, no cache = %s\n", Irp->Flags & IRP_PAGING_IO ? "TRUE" : "FALSE", Irp->Flags & IRP_NOCACHE ? "TRUE" : "FALSE");

    if (fcb->type == BTRFS_TYPE_DIRECTORY) {
        Status = STATUS_INVALID_DEVICE_REQUEST;
        goto exit;
    }
    
    if (!(Irp->Flags & IRP_PAGING_IO) && !FsRtlCheckLockForReadAccess(&fcb->lock, Irp)) {
        WARN("tried to read locked region\n");
        Status = STATUS_FILE_LOCK_CONFLICT;
        goto exit;
    }
    
    if (length == 0) {
        WARN("tried to read zero bytes\n");
        Status = STATUS_SUCCESS;
        goto exit;
    }
    
    if (start >= fcb->Header.FileSize.QuadPart) {
        TRACE("tried to read with offset after file end (%llx >= %llx)\n", start, fcb->Header.FileSize.QuadPart);
        Status = STATUS_END_OF_FILE;
        goto exit;
    }
    
    TRACE("FileObject %p fcb %p FileSize = %llx st_size = %llx (%p)\n", FileObject, fcb, fcb->Header.FileSize.QuadPart, fcb->inode_item.st_size, &fcb->inode_item.st_size);
//     int3;
    
    if (Irp->Flags & IRP_NOCACHE || !(IrpSp->MinorFunction & IRP_MN_MDL)) {
        data = map_user_buffer(Irp);
        
        if (Irp->MdlAddress && !data) {
            ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto exit;
        }
        
        if (length + start > fcb->Header.ValidDataLength.QuadPart) {
            RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), length - (fcb->Header.ValidDataLength.QuadPart - start));
            length = fcb->Header.ValidDataLength.QuadPart - start;
        }
    }
        
    if (!(Irp->Flags & IRP_NOCACHE)) {
        BOOL wait;
        
        Status = STATUS_SUCCESS;
        
        _SEH2_TRY {
            if (!FileObject->PrivateCacheMap) {
                CC_FILE_SIZES ccfs;
                
                ccfs.AllocationSize = fcb->Header.AllocationSize;
                ccfs.FileSize = fcb->Header.FileSize;
                ccfs.ValidDataLength = fcb->Header.ValidDataLength;
                
                TRACE("calling CcInitializeCacheMap (%llx, %llx, %llx)\n",
                            ccfs.AllocationSize.QuadPart, ccfs.FileSize.QuadPart, ccfs.ValidDataLength.QuadPart);
                CcInitializeCacheMap(FileObject, &ccfs, FALSE, cache_callbacks, FileObject);

                CcSetReadAheadGranularity(FileObject, READ_AHEAD_GRANULARITY);
            }
            
            // FIXME - uncomment this when async is working
    //         wait = IoIsOperationSynchronous(Irp) ? TRUE : FALSE;
            wait = TRUE;
            
            if (IrpSp->MinorFunction & IRP_MN_MDL) {
                CcMdlRead(FileObject,&IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus);
            } else {
                TRACE("CcCopyRead(%p, %llx, %x, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus);
                TRACE("sizes = %llx, %llx, %llx\n", fcb->Header.AllocationSize, fcb->Header.FileSize, fcb->Header.ValidDataLength);
                if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) {
                    TRACE("CcCopyRead failed\n");
                    
                    IoMarkIrpPending(Irp);
                    Status = STATUS_PENDING;
                    goto exit;
                }
                TRACE("CcCopyRead finished\n");
            }
        } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
            Status = _SEH2_GetExceptionCode();
        } _SEH2_END;
        
        if (NT_SUCCESS(Status)) {
            Status = Irp->IoStatus.Status;
            bytes_read = Irp->IoStatus.Information;
        } else
            ERR("EXCEPTION - %08x\n", Status);
    } else {