示例#1
0
static NTSTATUS
NdNtfsFlushUserStream (
    IN PIRP_CONTEXT IrpContext,
    IN PSCB Scb,
    IN PLONGLONG FileOffset OPTIONAL,
    IN ULONG Length
    )

/*++

Routine Description:

    This routine flushes a user stream as a top-level action.  To do so
    it checkpoints the current transaction first and frees all of the
    caller's snapshots.  After doing the flush, it snapshots the input
    Scb again, just in case the caller plans to do any more work on that
    stream.  If the caller needs to modify any other streams (presumably
    metadata), it must know to snapshot them itself after calling this
    routine.

Arguments:

    Scb - Stream to flush

    FileOffset - FileOffset at which the flush is to start, or NULL for
                 entire stream.

    Length - Number of bytes to flush.  Ignored if FileOffset not specified.

Return Value:

    Status of the flush

--*/

{
    IO_STATUS_BLOCK IoStatus;
    BOOLEAN ScbAcquired = FALSE;

    PAGED_CODE();

    //
    //  Checkpoint the current transaction and free all of its snapshots,
    //  in order to treat the flush as a top-level action with his own
    //  snapshots, etc.
    //
#if 0
    NtfsCheckpointCurrentTransaction( IrpContext );
    NtfsFreeSnapshotsForFcb( IrpContext, NULL );
#endif

    //
    //  Set the wait flag in the IrpContext so we don't hit a case where the
    //  reacquire below fails because we can't wait.  If our caller was asynchronous
    //  and we get this far we will continue synchronously.
    //

    SetFlag( IrpContext->State, IRP_CONTEXT_STATE_WAIT );

    //
    //  We must free the Scb now before calling through MM to prevent
    //  collided page deadlocks.
    //

    //
    //  We are about to flush the stream.  The Scb may be acquired exclusive
    //  and, thus, is linked onto the IrpContext or onto one higher
    //  up in the IoCallDriver stack.  We are about to make a
    //  call back into Ntfs which may acquire the Scb exclusive, but
    //  NOT put it onto the nested IrpContext exclusive queue which prevents
    //  the nested completion from freeing the Scb.
    //
    //  This is only a problem for Scb's without a paging resource.
    //
    //  We acquire the Scb via ExAcquireResourceExclusiveLite, sidestepping
    //  Ntfs bookkeeping, and release it via NtfsReleaseScb.
    //

	ScbAcquired = NtfsIsExclusiveScb( Scb );

    if (ScbAcquired) {
        if (Scb->Header.PagingIoResource == NULL) {
            NtfsAcquireResourceExclusive( IrpContext, Scb, TRUE );
        }
        NtfsReleaseScb( IrpContext, Scb );
    }

#ifdef  COMPRESS_ON_WIRE
    if (Scb->Header.FileObjectC != NULL) {

        PCOMPRESSION_SYNC CompressionSync = NULL;

        //
        //  Use a try-finally to clean up the compression sync.
        //

        try {

            NtfsSynchronizeUncompressedIo( Scb,
                                           NULL,
                                           0,
                                           TRUE,
                                           &CompressionSync );

        } finally {

            NtfsReleaseCompressionSync( CompressionSync );
        }
    }
示例#2
0
VOID
NtfsReleaseFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine releases the specified Fcb resource.  If the Fcb is acquired
    exclusive, and a transaction is still active, then the release is nooped
    in order to preserve two-phase locking.  If there is no longer an active
    transaction, then we remove the Fcb from the Exclusive Fcb List off the
    IrpContext, and clear the Flink as a sign.  Fcbs are released when the
    transaction is commited.

Arguments:

    Fcb - Fcb to release

Return Value:

    None.

--*/

{
    //
    //  Check if this resource is owned exclusively and we are at the last
    //  release for this transaction.
    //

    if (Fcb->ExclusiveFcbLinks.Flink != NULL) {

        if (Fcb->BaseExclusiveCount == 1) {

            //
            //  If there is a transaction then noop this request.
            //

            if (IrpContext->TransactionId != 0) {

                return;
            }

            RemoveEntryList( &Fcb->ExclusiveFcbLinks );
            Fcb->ExclusiveFcbLinks.Flink = NULL;


            //
            //  This is a good time to free any Scb snapshots for this Fcb.
            //

            NtfsFreeSnapshotsForFcb( IrpContext, Fcb );
        }

        Fcb->BaseExclusiveCount -= 1;
    }

    ASSERT((Fcb->ExclusiveFcbLinks.Flink == NULL && Fcb->BaseExclusiveCount == 0) ||
           (Fcb->ExclusiveFcbLinks.Flink != NULL && Fcb->BaseExclusiveCount != 0));

    ExReleaseResource( Fcb->Resource );
}