Ejemplo n.º 1
0
VOID
LfsGetActiveLsnRange (
    IN LFS_LOG_HANDLE LogHandle,
    OUT PLSN OldestLsn,
    OUT PLSN NextLsn
    )

/*++

Routine Description:

    Returns back the range that is active in the logfile from the oldest valid LSN to
    where the next active LSN will be. For external clients since it acquires the leb sync resource

Arguments:

    Lfcb - the logfile handle

    OldestLsn - returns the oldest active lsn

    NextLsn - returns the projected next lsn to be used

Return Value:

    None

--*/
{
    PLCH Lch;
    PLFCB Lfcb;

    PAGED_CODE();

    Lch = (PLCH) LogHandle;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    try {

        //
        //  Acquire the log file control block for this log file.
        //

        LfsAcquireLch( Lch );
        Lfcb = Lch->Lfcb;

        LfsGetActiveLsnRangeInternal( Lfcb, OldestLsn, NextLsn );


    } finally {
        LfsReleaseLch( Lch );
    }
}
Ejemplo n.º 2
0
LSN
LfsQueryLastLsn (
    IN LFS_LOG_HANDLE LogHandle
    )

/*++

Routine Description:

    This routine will return the most recent Lsn for this log record.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

Return Value:

    LSN - This is the last Lsn assigned in this log file.

--*/

{
    PLCH Lch;

    PLFCB Lfcb;

    LSN LastLsn;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsQueryLastLsn:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );

    Lch = (PLCH) LogHandle;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Acquire the log file control block for this log file.
        //

        LfsAcquireLch( Lch );
        Lfcb = Lch->Lfcb;

        //
        //  If the Log file has been closed then refuse access.
        //

        if (Lfcb == NULL) {

            ExRaiseStatus( STATUS_ACCESS_DENIED );
        }

        //
        //  Check that the client Id is valid.
        //

        LfsValidateClientId( Lfcb, Lch );

        //
        //  Copy the last Lsn out of the Lfcb.  If the last Lsn is
        //  does not correspond to a log record, we will return the
        //  zero Lsn.
        //

        if (FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN )) {

            LastLsn = LfsZeroLsn;

        } else {

            LastLsn = Lfcb->RestartArea->CurrentLsn;
        }

    } finally {

        DebugUnwind( LfsQueryLastLsn );

        //
        //  Release the Lfcb if acquired.
        //

        LfsReleaseLch( Lch );

        LfsDebugTrace(  0, Dbg, "Last Lsn (Low)    -> %08lx\n", LastLsn.LowPart );
        LfsDebugTrace(  0, Dbg, "Last Lsn (High)   -> %08lx\n", LastLsn.HighPart );
        LfsDebugTrace( -1, Dbg, "LfsQueryLastLsn:  Exit\n", 0 );
    }

    return LastLsn;
}
Ejemplo n.º 3
0
VOID
LfsReadLogRecord (
    IN LFS_LOG_HANDLE LogHandle,
    IN LSN FirstLsn,
    IN LFS_CONTEXT_MODE ContextMode,
    OUT PLFS_LOG_CONTEXT Context,
    OUT PLFS_RECORD_TYPE RecordType,
    OUT TRANSACTION_ID *TransactionId,
    OUT PLSN UndoNextLsn,
    OUT PLSN PreviousLsn,
    OUT PULONG BufferLength,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

    This routine initiates the query operation.  It returns the log record
    in question and a context structure used by the Lfs to return related
    log records.  The caller specifies what mode of query to use.  He may
    walk backwards through the file by Undo records or all records for
    this client linked through the previous Lsn fields.  He may also look
    forwards through the file for all records for the issuing client.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    FirstLsn - Starting record for this query operation.

    ContextMode - Method of query.

    Context - Supplies the address to store a pointer to the Lfs created
              context structure.

    RecordType - Supplies the address to store the record type of this
                 log record.

    TransactionId - Supplies the address to store the transaction Id of
                    this log record.

    UndoNextLsn - Supplies the address to store the Undo Next Lsn for this
                  log record.

    PreviousLsn - Supplies the address to store the Previous Lsn for this
                  log record.

    BufferLength - This is the length of the log data.

    Buffer - This is a pointer to the start of the log data.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    PLFS_CLIENT_RECORD ClientRecord;

    PLCH Lch;

    PLFCB Lfcb;

    PLfsLCB Lcb = NULL;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsReadLogRecord:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle        -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "First Lsn (Low)   -> %08lx\n", FirstLsn.LowPart );
    LfsDebugTrace(  0, Dbg, "First Lsn (High)  -> %08lx\n", FirstLsn.HighPart );
    LfsDebugTrace(  0, Dbg, "Context Mode      -> %08lx\n", ContextMode );

    Lch = (PLCH) LogHandle;

    //
    //  Check that the context mode is valid.
    //

    switch (ContextMode) {

    case LfsContextUndoNext :
    case LfsContextPrevious :
    case LfsContextForward :

        break;

    default:

        LfsDebugTrace( 0, Dbg, "Invalid context mode -> %08x\n", ContextMode );
        ExRaiseStatus( STATUS_INVALID_PARAMETER );
    }

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    try {

        //
        //  Use a try-finally to facilitate cleanup.
        //

        try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            //
            //  Check that the given Lsn is in the legal range for this client.
            //

            ClientRecord = LfsAdd2Ptr( Lfcb->ClientArray,
                                    Lch->ClientArrayByteOffset,
                                    PLFS_CLIENT_RECORD );

            if (!LfsVerifyClientLsnInRange( Lfcb, ClientRecord, FirstLsn )) {

                ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
            }

            //
            //  We can give up the Lfcb as we know the Lsn is within the file.
            //

            LfsReleaseLch( Lch );

            //
            //  Allocate and initialize a context structure.
            //

            LfsAllocateLcb( &Lcb );

            LfsInitializeLcb( Lcb,
                              Lch->ClientId,
                              ContextMode );

            //
            //  Find the log record indicated by the given Lsn.
            //

            LfsFindLogRecord( Lfcb,
                              Lcb,
                              FirstLsn,
                              RecordType,
                              TransactionId,
                              UndoNextLsn,
                              PreviousLsn,
                              BufferLength,
                              Buffer );

            //
            //  Update the client's arguments.
            //

            *Context = Lcb;
            Lcb = NULL;

        } finally {

            DebugUnwind( LfsReadLogRecord );

            //
            //  Release the log file control block if held.
            //

            LfsReleaseLch( Lch );

            //
            //  Deallocate the context block if an error occurred.
            //

            if (Lcb != NULL) {

                LfsDeallocateLcb( Lcb );
            }

            LfsDebugTrace(  0, Dbg, "Context       -> %08lx\n", *Context );
            LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
            LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", *Buffer );
            LfsDebugTrace( -1, Dbg, "LfsReadLogRecord:  Exit\n", 0 );
        }

    } except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return;
}
Ejemplo n.º 4
0
VOID
LfsTerminateLogQuery (
    IN LFS_LOG_HANDLE LogHandle,
    IN LFS_LOG_CONTEXT Context
    )

/*++

Routine Description:

    This routine is called when a client has completed his query operation
    and wishes to deallocate any resources acquired by the Lfs to
    perform the log file query.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    Context - Supplies the address to store a pointer to the Lfs created
              context structure.

Return Value:

    None

--*/

{
    PLCH Lch;
    PLfsLCB Lcb;

    PLFCB Lfcb;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsTerminateLogQuery:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Context       -> %08lx\n", Context );

    Lch = (PLCH) LogHandle;
    Lcb = (PLfsLCB) Context;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Acquire the log file control block for this log file.
        //

        LfsAcquireLch( Lch );
        Lfcb = Lch->Lfcb;

        //
        //  If the Log file has been closed then refuse access.
        //

        if (Lfcb == NULL) {

            try_return( NOTHING );
        }

        //
        //  Check that the client Id is valid.
        //

        LfsValidateClientId( Lfcb, Lch );

        //
        //  Check that the context structure is valid.
        //

        LfsValidateLcb( Lcb, Lch );

        //
        //  Deallocate the context block.
        //

        LfsDeallocateLcb( Lcb );

    try_exit:  NOTHING;
    } finally {

        DebugUnwind( LfsTerminateLogQuery );

        //
        //  Release the Lfcb if acquired.
        //

        LfsReleaseLch( Lch );

        LfsDebugTrace( -1, Dbg, "LfsTerminateLogQuery:  Exit\n", 0 );
    }

    return;
}
Ejemplo n.º 5
0
BOOLEAN
LfsReadNextLogRecord (
    IN LFS_LOG_HANDLE LogHandle,
    IN OUT LFS_LOG_CONTEXT Context,
    OUT PLFS_RECORD_TYPE RecordType,
    OUT TRANSACTION_ID *TransactionId,
    OUT PLSN UndoNextLsn,
    OUT PLSN PreviousLsn,
    OUT PLSN Lsn,
    OUT PULONG BufferLength,
    OUT PVOID *Buffer
    )

/*++

Routine Description:

    This routine is called to continue a query operation.  The Lfs uses
    private information stored in the context structure to determine the
    next log record to return to the caller.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    Context - Supplies the address to store a pointer to the Lfs created
              context structure.

    Lsn - Lsn for this log record.

    RecordType - Supplies the address to store the record type of this
                 log record.

    TransactionId - Supplies the address to store the transaction Id of
                    this log record.

    UndoNextLsn - Supplies the address to store the Undo Next Lsn for this
                  log record.

    PreviousLsn - Supplies the address to store the Previous Lsn for this
                  log record.

    BufferLength - This is the length of the log data.

    Buffer - This is a pointer to the start of the log data.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    PLCH Lch;

    PLFCB Lfcb;

    PLfsLCB Lcb;

    BOOLEAN FoundNextLsn;

    BOOLEAN UnwindRememberLcbFields;
    PBCB UnwindRecordHeaderBcb;
    PLFS_RECORD_HEADER UnwindRecordHeader;
    PVOID UnwindCurrentLogRecord;
    BOOLEAN UnwindAuxilaryBuffer;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsReadNextLogRecord:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Context       -> %08lx\n", Context );

    FoundNextLsn = FALSE;

    UnwindRememberLcbFields = FALSE;

    Lch = (PLCH) LogHandle;
    Lcb = (PLfsLCB) Context;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    try {

        //
        //  Use a try-finally to facilitate cleanup.
        //

        try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            //
            //  Check that the context structure is valid.
            //

            LfsValidateLcb( Lcb, Lch );

            //
            //  Remember any context fields to be overwritten.
            //

            UnwindRememberLcbFields = TRUE;

            UnwindRecordHeaderBcb = Lcb->RecordHeaderBcb;
            Lcb->RecordHeaderBcb = NULL;

            UnwindRecordHeader = Lcb->RecordHeader;
            UnwindCurrentLogRecord = Lcb->CurrentLogRecord;

            UnwindAuxilaryBuffer = Lcb->AuxilaryBuffer;
            Lcb->AuxilaryBuffer = FALSE;

            //
            //  Find the next Lsn number based on the current Lsn number in
            //  the context block.
            //

            if (LfsFindClientNextLsn( Lfcb, Lcb, Lsn )) {

                //
                //  We can give up the Lfcb as we know the Lsn is within the file.
                //

                LfsReleaseLfcb( Lfcb );

                //
                //  Cleanup the context block so we can do the next search.
                //

                Lcb->CurrentLogRecord = NULL;
                Lcb->AuxilaryBuffer = FALSE;

                //
                //  Perform the work of getting the log record.
                //

                LfsFindLogRecord( Lfcb,
                                  Lcb,
                                  *Lsn,
                                  RecordType,
                                  TransactionId,
                                  UndoNextLsn,
                                  PreviousLsn,
                                  BufferLength,
                                  Buffer );

                FoundNextLsn = TRUE;
            }

        } finally {

            DebugUnwind( LfsReadNextLogRecord );

            //
            //  If we exited due to an error, we have to restore the context
            //  block.
            //

            if (UnwindRememberLcbFields) {

                if (AbnormalTermination()) {

                    //
                    //  If the record header in the context block is not
                    //  the same as we started with.  Then we unpin that
                    //  data.
                    //

                    if (Lcb->RecordHeaderBcb != NULL) {

                        CcUnpinData( Lcb->RecordHeaderBcb );

                    }

                    if (Lcb->CurrentLogRecord != NULL
                        && Lcb->AuxilaryBuffer == TRUE) {

                        ExFreePool( Lcb->CurrentLogRecord );
                    }

                    Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb;
                    Lcb->RecordHeader = UnwindRecordHeader;
                    Lcb->CurrentLogRecord = UnwindCurrentLogRecord;
                    Lcb->AuxilaryBuffer = UnwindAuxilaryBuffer;

                //
                //  Otherwise, if we have successfully found the next Lsn,
                //  we free up any resources being held from the previous search.
                //

                } else if (FoundNextLsn ) {

                    if (UnwindRecordHeaderBcb != NULL) {

                        CcUnpinData( UnwindRecordHeaderBcb );
                    }

                    if (UnwindCurrentLogRecord != NULL
                        && UnwindAuxilaryBuffer == TRUE) {

                        ExFreePool( UnwindCurrentLogRecord );
                    }

                //
                //  Restore the Bcb and auxilary buffer field for the final
                //  cleanup.
                //

                } else {

                    if (UnwindRecordHeaderBcb != NULL) {

                        if (Lcb->RecordHeaderBcb != NULL) {

                            CcUnpinData( UnwindRecordHeaderBcb );

                        } else {

                            Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb;
                        }
                    }

                    if (UnwindAuxilaryBuffer) {

                        if (Lcb->CurrentLogRecord == UnwindCurrentLogRecord) {

                            Lcb->AuxilaryBuffer = TRUE;

                        } else {

                            ExFreePool( UnwindCurrentLogRecord );
                        }
                    }
                }
            }

            //
            //  Release the log file control block if held.
            //

            LfsReleaseLch( Lch );

            LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn->LowPart );
            LfsDebugTrace(  0, Dbg, "Lsn (High)    -> %08lx\n", Lsn->HighPart );
            LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
            LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", *Buffer );
            LfsDebugTrace( -1, Dbg, "LfsReadNextLogRecord:  Exit\n", 0 );
        }

    } except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return FoundNextLsn;
}
Ejemplo n.º 6
0
VOID
LfsReadRestartArea (
    IN LFS_LOG_HANDLE LogHandle,
    IN OUT PULONG BufferLength,
    IN PVOID Buffer,
    OUT PLSN Lsn
    )

/*++

Routine Description:

    This routine is called by the client when he wishes to read his restart
    area in the log file.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    BufferLength - On entry it is the length of the user buffer.  On exit
                   it is the size of the data stored in the buffer.

    Buffer - Pointer to the buffer where the client restart data is to be
             copied.

    Lsn - This is the Lsn for client restart area.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    BOOLEAN UsaError;

    PLCH Lch;

    PLFS_CLIENT_RECORD ClientRecord;

    PLFS_RECORD_HEADER RecordHeader;
    PBCB RecordHeaderBcb;

    PLFCB Lfcb;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsReadRestartArea:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
    LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", Buffer );

    RecordHeaderBcb = NULL;

    Lch = (PLCH) LogHandle;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    try {

        //
        //  Use a try-finally to facilitate cleanup.
        //

        try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            ClientRecord = LfsAdd2Ptr( Lfcb->ClientArray,
                                    Lch->ClientArrayByteOffset,
                                    PLFS_CLIENT_RECORD );

            //
            //  If the client doesn't have a restart area, go ahead and exit
            //  now.
            //

            if ( ClientRecord->ClientRestartLsn.QuadPart == 0 ) {                                                      //**** xxEqlZero( ClientRecord->ClientRestartLsn )

                //
                //  We show there is no restart area by returning a length
                //  of zero.  We also set the Lsn value to zero so that
                //  we can catch it if the user tries to use the Lsn.
                //

                LfsDebugTrace( 0, Dbg, "No client restart area exists\n", 0 );

                *BufferLength = 0;
                *Lsn = LfsZeroLsn;

                try_return( NOTHING );
            }

            //
            //  Release the Lfcb as we won't be modifying any fields in it.
            //

            LfsReleaseLfcb( Lfcb );

            //
            //  Pin the log record for this Lsn.
            //

            LfsPinOrMapLogRecordHeader( Lfcb,
                                        ClientRecord->ClientRestartLsn,
                                        FALSE,
                                        FALSE,
                                        &UsaError,
                                        &RecordHeader,
                                        &RecordHeaderBcb );

            //
            //  If the Lsn values don't match, then the disk is corrupt.
            //

            if ( ClientRecord->ClientRestartLsn.QuadPart != RecordHeader->ThisLsn.QuadPart ) {                         //**** xxNeq( ClientRecord->ClientRestartLsn, RecordHeader->ThisLsn )

                ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
            }


            //
            //  Check that the user's buffer is big enough to hold the restart
            //  data.  We raise an error status for this error.
            //

            if (RecordHeader->ClientDataLength > *BufferLength) {

                LfsDebugTrace( 0, Dbg, "Client buffer is too small\n", 0 );
                *BufferLength = 0;
                *Lsn = LfsZeroLsn;
                ExRaiseStatus( STATUS_BUFFER_OVERFLOW );
            }


            //
            //  Use the cache manager to copy the data into the user's buffer.
            //

            LfsCopyReadLogRecord( Lfcb,
                                  RecordHeader,
                                  Buffer );

            //
            //  Pass the length and the Lsn of the restart area back to the
            //  caller.
            //

            *BufferLength = RecordHeader->ClientDataLength;
            *Lsn = RecordHeader->ThisLsn;

        try_exit: NOTHING;
        } finally {

            DebugUnwind( LfsReadRestartArea );

            //
            //  Release the log file control block if held.
            //

            LfsReleaseLch( Lch );

            //
            //  Unpin the log record header for the client restart if pinned.
            //

            if (RecordHeaderBcb != NULL) {

                CcUnpinData( RecordHeaderBcb );
            }

            LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn->LowPart );
            LfsDebugTrace(  0, Dbg, "Lsn (High)    -> %08lx\n", Lsn->HighPart );
            LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", *BufferLength );
            LfsDebugTrace( -1, Dbg, "LfsReadRestartArea:  Exit\n", 0 );
        }

    } except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return;
}
Ejemplo n.º 7
0
VOID
LfsSetBaseLsn (
    IN LFS_LOG_HANDLE LogHandle,
    IN LSN BaseLsn
    )

/*++

Routine Description:

    This routine is called by the client to notify the log service of the
    oldest Lsn he expects to need during restart.  The Lfs is allowed to
    reuse any part of the circular log file which logically precedes
    this Lsn.  A client may only specify a Lsn which follows the previous
    Lsn specified by this client.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    BaseLsn - This is the oldest Lsn the client may require during a
              restart.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    PLCH Lch;

    PLFCB Lfcb;

    PLFS_CLIENT_RECORD ClientRecord;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsSetBaseLsn:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle        -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Base Lsn (Low)    -> %08lx\n", BaseLsn.LowPart );
    LfsDebugTrace(  0, Dbg, "Base Lsn (High)   -> %08lx\n", BaseLsn.HighPart );

    Lch = (PLCH) LogHandle;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    try {

        //
        //  Use a try-finally to facilitate cleanup.
        //

        try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            ClientRecord = LfsAdd2Ptr( Lfcb->ClientArray,
                                    Lch->ClientArrayByteOffset,
                                    PLFS_CLIENT_RECORD );

            //
            //  We simply call the worker routine to advance the base lsn.
            //  If we moved forward in the file, we will put our restart area in the
            //  queue.
            //

            LfsSetBaseLsnPriv( Lfcb,
                               ClientRecord,
                               BaseLsn );

            LfsWriteLfsRestart( Lfcb, Lfcb->RestartAreaSize, FALSE );

        } finally {

            DebugUnwind( LfsSetBaseLsn );

            //
            //  Release the log file control block if held.
            //

            LfsReleaseLch( Lch );

            LfsDebugTrace( -1, Dbg, "LfsSetBaseLsn:  Exit\n", 0 );
        }

    } except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return;
}
Ejemplo n.º 8
0
VOID
LfsWriteRestartArea (
    IN LFS_LOG_HANDLE LogHandle,
    IN ULONG BufferLength,
    IN PVOID Buffer,
    OUT PLSN Lsn
    )

/*++

Routine Description:

    This routine is called by the client to write a restart area to the
    disk.  This routine will not return to the caller until the client
    restart area and all prior Lsn's have been flushed and the Lfs
    restart area on the disk has been updated.

    On return, all log records up to and including 'Lsn' have been flushed
    to the disk.

Arguments:

    LogHandle - Pointer to private Lfs structure used to identify this
                client.

    BufferLength - On entry it is the length of the user buffer.

    Buffer - Pointer to the buffer where the client restart data resides.

    Lsn - This is the Lsn for this write operation.  On input, this will be the
          new Base Lsn for this client.

          ****  This was used to prevent adding an interface change to
                the Beta release.

Return Value:

    None

--*/

{
    volatile NTSTATUS Status = STATUS_SUCCESS;

    PLCH Lch;

    PLFCB Lfcb;

    PLFS_CLIENT_RECORD ClientRecord;

    LFS_WRITE_ENTRY WriteEntry;

    PAGED_CODE();

    LfsDebugTrace( +1, Dbg, "LfsWriteRestartArea:  Entered\n", 0 );
    LfsDebugTrace(  0, Dbg, "Log Handle    -> %08lx\n", LogHandle );
    LfsDebugTrace(  0, Dbg, "Buffer Length -> %08lx\n", BufferLength );
    LfsDebugTrace(  0, Dbg, "Buffer        -> %08lx\n", Buffer );

    Lch = (PLCH) LogHandle;

    //
    //  Check that the structure is a valid log handle structure.
    //

    LfsValidateLch( Lch );

    //
    //  Use a try-except to catch errors.
    //

    try {

        //
        //  Use a try-finally to facilitate cleanup.
        //

        try {

            //
            //  Acquire the log file control block for this log file.
            //

            LfsAcquireLch( Lch );
            Lfcb = Lch->Lfcb;

            //
            //  If the Log file has been closed then refuse access.
            //

            if (Lfcb == NULL) {

                ExRaiseStatus( STATUS_ACCESS_DENIED );
            }

            //
            //  Check that the client Id is valid.
            //

            LfsValidateClientId( Lfcb, Lch );

            ClientRecord = LfsAdd2Ptr( Lfcb->ClientArray,
                                    Lch->ClientArrayByteOffset,
                                    PLFS_CLIENT_RECORD );

            //
            //  Go ahead and update the Base Lsn in the client area if the value
            //  given is not zero.
            //

            if ( Lsn->QuadPart != 0 ) {                                                                                //**** xxNeqZero( *Lsn )

                LfsSetBaseLsnPriv( Lfcb,
                                   ClientRecord,
                                   *Lsn );
            }

            //
            //  Write this restart area as a log record into a log page.
            //

            WriteEntry.Buffer = Buffer;
            WriteEntry.ByteLength = BufferLength;

            LfsWriteLogRecordIntoLogPage( Lfcb,
                                          Lch,
                                          1,
                                          &WriteEntry,
                                          LfsClientRestart,
                                          NULL,
                                          LfsZeroLsn,
                                          LfsZeroLsn,
                                          0,
                                          TRUE,
                                          Lsn );

            //
            //  Update the restart area for the client.
            //

            ClientRecord->ClientRestartLsn = *Lsn;

            //
            //  Write the restart area to the disk.
            //

            LfsWriteLfsRestart( Lfcb, Lfcb->RestartAreaSize, TRUE );

        } finally {

            DebugUnwind( LfsWriteRestartArea );

            //
            //  Release the log file control block if still held.
            //

            LfsReleaseLch( Lch );

            LfsDebugTrace(  0, Dbg, "Lsn (Low)     -> %08lx\n", Lsn->LowPart );
            LfsDebugTrace(  0, Dbg, "Log (High)    -> %08lx\n", Lsn->HighPart );
            LfsDebugTrace( -1, Dbg, "LfsWriteRestartArea:  Exit\n", 0 );
        }

    } except (LfsExceptionFilter( GetExceptionInformation() )) {

        Status = GetExceptionCode();
    }

    if (Status != STATUS_SUCCESS) {

        ExRaiseStatus( Status );
    }

    return;
}