/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    Flush.c

Abstract:

    This module implements the File Flush buffers routine for Rx called by the
    dispatch driver.

    In a future version of the wrapper, it may be that flush will be routed thru lowio.

Author:

    Joe Linn     [JoeLinn]    15-dec-1994

Revision History:

--*/

#include "precomp.h"
#pragma hdrstop

//
//  The local debug trace level
//

#define Dbg                              (DEBUG_TRACE_FLUSH)

//RXSTATUS
//RxLowIoFlushShell (
//    IN PRX_CONTEXT RxContext
//    );
//
//RXSTATUS
//RxLowIoFlushShellCompletion (
//    IN PRX_CONTEXT RxContext
//    );

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RxCommonFlushBuffers)
#pragma alloc_text(PAGE, RxFlushFile)
#endif



NTSTATUS
RxCommonFlushBuffers ( RXCOMMON_SIGNATURE )

/*++

Routine Description:

    This is the common routine for flushing file buffers.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    RXSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    RxCaptureRequestPacket;
    RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock; RxCaptureFileObject;
    NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);

    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;


    BOOLEAN FcbAcquired = FALSE;

    PAGED_CODE();

    RxDbgTrace(+1, Dbg, ("RxCommonFlush...IrpC %08lx, Fobx %08lx, Fcb %08lx\n",
                                       RxContext, capFobx, capFcb));
    RxLog(("%s %lx %lx %lx\n","slF",RxContext,capFcb,capFobx));

    //
    //  CcFlushCache is always synchronous, so if we can't wait enqueue
    //  the irp to the Fsp.

    if ( !FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT) ) {

        Status = RxFsdPostRequest( RxContext );

        RxDbgTrace(-1, Dbg, ("RxCommonFlushBuffers -> %08lx\n", Status ));
        return Status;
    }

    Status = STATUS_SUCCESS;

    try {

        //
        //  Case on the type of open that we are trying to flush
        //

        switch (TypeOfOpen) {

        case RDBSS_NTC_STORAGE_TYPE_FILE:

            RxDbgTrace(0, Dbg, ("Flush User File Open\n", 0));

            Status = RxAcquireExclusiveFcb( RxContext, capFcb );

            if (Status != STATUS_SUCCESS) break;

            FcbAcquired = TRUE;

            //
            //  If the file is cached then flush its cache
            //

            Status = RxFlushFile( RxContext, capFcb );

            if (!NT_SUCCESS( Status )) break;

            //rdrs don't do this.....only local FSs
            ////
            ////  Check if we should be changing the time or file size
            //
            //RxAdjustFileTimesAndSize(RXCOMMON_ARGUMENTS);

            // if we make this lowio.........
            ////
            ////  Initialize LowIO_CONTEXT block in the RxContext and Calldown
            //
            //RxInitializeLowIoContext(LowIoContext,LOWIO_OP_FLUSH);
            //
            //Status = RxLowIoFlushShell(RxContext);

            MINIRDR_CALL(Status,RxContext,capFcb->MRxDispatch,MRxFlush,(RxContext));
            break;

        case RDBSS_NTC_SPOOLFILE:

            RxDbgTrace(0, Dbg, ("Flush Sppol File\n", 0));

            Status = RxAcquireExclusiveFcb( RxContext, capFcb );

            if (Status != STATUS_SUCCESS) break;

            FcbAcquired = TRUE;

            // should this be low io???
            ////
            ////  Initialize LowIO_CONTEXT block in the RxContext and Calldown
            //
            //RxInitializeLowIoContext(LowIoContext,LOWIO_OP_FLUSH);
            //
            //Status = RxLowIoFlushShell(RxContext);

            MINIRDR_CALL(Status,RxContext,capFcb->MRxDispatch,MRxFlush,(RxContext));
            break;

        default:

            Status = STATUS_INVALID_DEVICE_REQUEST;
        }


    } finally {

        DebugUnwind( RxCommonFlushBuffers );

        if (FcbAcquired) { RxReleaseFcb( RxContext, capFcb ); }

        //
        //  If this is a normal termination then pass the request on
        //  to the target device object.
        //

        if (!AbnormalTermination()) {

            NOTHING;

        }

    }

    RxDbgTrace(-1, Dbg, ("RxCommonFlushBuffers -> %08lx\n", Status));
    return Status;
}


#if 0
BUGBUG
THIS CODE WOULD BE USED IF THIS IS CHANGED TO LOWIO


NTSTATUS
RxLowIoFlushShellCompletion (
    IN PRX_CONTEXT RxContext
    )

/*++

Routine Description:

    these completion shells are pretty similar. BUT as the error handling gets more
    robust the routines will become increasingly dissimilar. for flush, everything is synchronous...that's
    a difference with read/write/lock; we keep the same declarations and format for later when we decide to roll up the
    common part of these routines.

    This routine postprocesses a flush request after it comes back from the
    minirdr. It is the complement of LowIoFlushShell.


Arguments:

    RxContext - the usual

Return Value:

    whatever value supplied by the caller or STATUS_MORE_PROCESSING_REQUIRED.

--*/

{
    NTSTATUS Status;
    RxCaptureRequestPacket;
    RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
    BOOLEAN  SynchronousIo = !BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION);
    BOOLEAN  PagingIo      = BooleanFlagOn(capReqPacket->Flags, IRP_PAGING_IO);
    ERESOURCE_THREAD ThisResourceThreadId;


    Status = RxContext->StoredStatus;
    RxDbgTrace(+1, Dbg, ("RxLowIoFlushShellCompletion  entry  Status = %08lx\n", Status));
    RxLog(("FlshShlComp %x\n",RxContext));

    //switch (Status) {
    //case STATUS_SUCCESS:
    //    break;
    //case STATUS_CONNECTION_INVALID:
    //    //joejoe here is where the failover will happen
    //    //first we give the local guy current minirdr another chance...then we go
    //    //to fullscale retry
    //    //return(RxStatus(DISCONNECTED));   //special....let LowIo get us back
    //    break;
    //}

    capReqPacket->IoStatus.Status = Status;

    RxDbgTrace(-1, Dbg, ("RxLowIoFlushShellCompletion  exit  Status = %08lx\n", Status));
    return(Status);
    //NOTE THAT THE ASYNC COMPLETION TAIL IS MISSING
}

#define RxSdwFlush(RXCONTEXT)  {NOTHING;}
}
NTSTATUS
RxLowIoFlushShell (
    IN PRX_CONTEXT RxContext
    )

/*++

Routine Description:

    This routine preprocesses a Flush request before it goes down to the minirdr. It does callouts
    to handle compression, buffering and shadowing. It is the opposite number of LowIoFlushShellCompletion.
    By the time we get here, we are going to the wire.
    Flush buffering was already tried in the UncachedFlush strategy

Arguments:

    RxContext - the usual

Return Value:

    whatever value is returned by a callout....or by LowIo.

--*/

{
    NTSTATUS Status;
    RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
    PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;

    RxDbgTrace(+1, Dbg, ("RxLowIoFlushShell  entry             %08lx\n", 0));
    RxLog(("FlshShl in%x\n",RxContext));
    if (FlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED)) {
        RxSdwFlush(RxContext);
    }

    Status = RxLowIoSubmit(RxContext,RxLowIoFlushShellCompletion);
    RxDbgTrace(-1, Dbg, ("RxLowIoFlushShell  exit  Status = %08lx\n", Status));
    return(Status);
}
#endif