diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/lfs/write.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/lfs/write.c')
-rw-r--r-- | private/ntos/lfs/write.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/private/ntos/lfs/write.c b/private/ntos/lfs/write.c new file mode 100644 index 000000000..580bbd10e --- /dev/null +++ b/private/ntos/lfs/write.c @@ -0,0 +1,475 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + Write.c + +Abstract: + + This module implements the user routines which write log records into + or flush portions of the log file. + +Author: + + Brian Andrew [BrianAn] 20-June-1991 + +Revision History: + +--*/ + +#include "lfsprocs.h" + +// +// The debug trace level +// + +#define Dbg (DEBUG_TRACE_WRITE) + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, LfsFlushToLsn) +#pragma alloc_text(PAGE, LfsForceWrite) +#pragma alloc_text(PAGE, LfsWrite) +#endif + + +BOOLEAN +LfsWrite ( + IN LFS_LOG_HANDLE LogHandle, + IN ULONG NumberOfWriteEntries, + IN PLFS_WRITE_ENTRY WriteEntries, + IN LFS_RECORD_TYPE RecordType, + IN TRANSACTION_ID *TransactionId OPTIONAL, + IN LSN UndoNextLsn, + IN LSN PreviousLsn, + IN LONG UndoRequirement, + OUT PLSN Lsn + ) + +/*++ + +Routine Description: + + This routine is called by a client to write a log record to the log file. + The log record is lazy written and is not guaranteed to be on the disk + until a subsequent LfsForceWrie or LfsWriteRestartArea or until + an LfsFlushtoLsn is issued withan Lsn greater-than or equal to the Lsn + returned from this service. + +Arguments: + + LogHandle - Pointer to private Lfs structure used to identify this + client. + + NumberOfWriteEntries - Number of components of the log record. + + WriteEntries - Pointer to an array of write entries. + + RecordType - Lfs defined type for this log record. + + TransactionId - Id value used to group log records by complete transaction. + + UndoNextLsn - Lsn of a previous log record which needs to be undone in + the event of a client restart. + + PreviousLsn - Lsn of the immediately previous log record for this client. + + Lsn - Lsn to be associated with this log record. + +Return Value: + + BOOLEAN - Advisory, TRUE indicates that less than 1/4 of the log file is + available. + +--*/ + +{ + volatile NTSTATUS Status = STATUS_SUCCESS; + + BOOLEAN LogFileFull = FALSE; + PLCH Lch; + + PLFCB Lfcb; + + PAGED_CODE(); + + DebugTrace( +1, Dbg, "LfsWrite: Entered\n", 0 ); + DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); + DebugTrace( 0, Dbg, "NumberOfWriteEntries -> %08lx\n", NumberOfWriteEntries ); + DebugTrace( 0, Dbg, "WriteEntries -> %08lx\n", WriteEntries ); + DebugTrace( 0, Dbg, "Record Type -> %08lx\n", RecordType ); + DebugTrace( 0, Dbg, "Transaction Id -> %08lx\n", TransactionId ); + DebugTrace( 0, Dbg, "UndoNextLsn (Low) -> %08lx\n", UndoNextLsn.LowPart ); + DebugTrace( 0, Dbg, "UndoNextLsn (High) -> %08lx\n", UndoNextLsn.HighPart ); + DebugTrace( 0, Dbg, "PreviousLsn (Low) -> %08lx\n", PreviousLsn.LowPart ); + DebugTrace( 0, Dbg, "PreviousLsn (High) -> %08lx\n", PreviousLsn.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 ); + + // + // Write the log record. + // + + LogFileFull = LfsWriteLogRecordIntoLogPage( Lfcb, + Lch, + NumberOfWriteEntries, + WriteEntries, + RecordType, + TransactionId, + UndoNextLsn, + PreviousLsn, + UndoRequirement, + FALSE, + Lsn ); + + } finally { + + DebugUnwind( LfsWrite ); + + // + // Release the log file control block if held. + // + + LfsReleaseLch( Lch ); + + DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); + DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); + DebugTrace( -1, Dbg, "LfsWrite: Exit\n", 0 ); + } + + } except (LfsExceptionFilter( GetExceptionInformation() )) { + + Status = GetExceptionCode(); + } + + if (Status != STATUS_SUCCESS) { + + ExRaiseStatus( Status ); + } + + return LogFileFull; +} + + +BOOLEAN +LfsForceWrite ( + IN LFS_LOG_HANDLE LogHandle, + IN ULONG NumberOfWriteEntries, + IN PLFS_WRITE_ENTRY WriteEntries, + IN LFS_RECORD_TYPE RecordType, + IN TRANSACTION_ID *TransactionId, + IN LSN UndoNextLsn, + IN LSN PreviousLsn, + IN LONG UndoRequirement, + OUT PLSN Lsn + ) + +/*++ + +Routine Description: + + This routine is called by a client to write a log record to the log file. + This is idendical to LfsWrite except that on return the log record is + guaranteed to be on disk. + +Arguments: + + LogHandle - Pointer to private Lfs structure used to identify this + client. + + NumberOfWriteEntries - Number of components of the log record. + + WriteEntries - Pointer to an array of write entries. + + RecordType - Lfs defined type for this log record. + + TransactionId - Id value used to group log records by complete transaction. + + UndoNextLsn - Lsn of a previous log record which needs to be undone in + the event of a client restart. + + PreviousLsn - Lsn of the immediately previous log record for this client. + + Lsn - Lsn to be associated with this log record. + +Return Value: + + BOOLEAN - Advisory, TRUE indicates that less than 1/4 of the log file is + available. + +--*/ + +{ + volatile NTSTATUS Status = STATUS_SUCCESS; + + PLCH Lch; + + PLFCB Lfcb; + BOOLEAN LogFileFull = FALSE; + + PAGED_CODE(); + + DebugTrace( +1, Dbg, "LfsForceWrite: Entered\n", 0 ); + DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); + DebugTrace( 0, Dbg, "NumberOfWriteEntries -> %08lx\n", NumberOfWriteEntries ); + DebugTrace( 0, Dbg, "WriteEntries -> %08lx\n", WriteEntries ); + DebugTrace( 0, Dbg, "Record Type -> %08lx\n", RecordType ); + DebugTrace( 0, Dbg, "Transaction Id -> %08lx\n", TransactionId ); + DebugTrace( 0, Dbg, "UndoNextLsn (Low) -> %08lx\n", UndoNextLsn.LowPart ); + DebugTrace( 0, Dbg, "UndoNextLsn (High) -> %08lx\n", UndoNextLsn.HighPart ); + DebugTrace( 0, Dbg, "PreviousLsn (Low) -> %08lx\n", PreviousLsn.LowPart ); + DebugTrace( 0, Dbg, "PreviousLsn (High) -> %08lx\n", PreviousLsn.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 ); + + // + // Write the log record. + // + + LogFileFull = LfsWriteLogRecordIntoLogPage( Lfcb, + Lch, + NumberOfWriteEntries, + WriteEntries, + RecordType, + TransactionId, + UndoNextLsn, + PreviousLsn, + UndoRequirement, + TRUE, + Lsn ); + + // + // The call to add this lbcb to the workque is guaranteed to release + // the Lfcb if this thread may do the Io. + // + + LfsFlushToLsnPriv( Lfcb, *Lsn ); + + } finally { + + DebugUnwind( LfsForceWrite ); + + // + // Release the log file control block if held. + // + + LfsReleaseLch( Lch ); + + DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); + DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); + DebugTrace( -1, Dbg, "LfsForceWrite: Exit\n", 0 ); + } + + } except (LfsExceptionFilter( GetExceptionInformation() )) { + + Status = GetExceptionCode(); + } + + if (Status != STATUS_SUCCESS) { + + ExRaiseStatus( Status ); + } + + return LogFileFull; +} + + +VOID +LfsFlushToLsn ( + IN LFS_LOG_HANDLE LogHandle, + IN LSN Lsn + ) + +/*++ + +Routine Description: + + This routine is called by a client to insure that all log records + to a certain point have been flushed to the file. This is done by + checking if the desired Lsn has even been written at all. If so we + check if it has been flushed to the file. If not, we simply write + the current restart area to the disk. + +Arguments: + + LogHandle - Pointer to private Lfs structure used to identify this + client. + + Lsn - This is the Lsn that must be on the disk on return from this + routine. + +Return Value: + + None + +--*/ + +{ + volatile NTSTATUS Status = STATUS_SUCCESS; + + PLCH Lch; + + PLFCB Lfcb; + + PAGED_CODE(); + + DebugTrace( +1, Dbg, "LfsFlushToLsn: Entered\n", 0 ); + DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); + DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn.LowPart ); + DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn.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 we will assume the Lsn has been flushed. + // + + if (Lfcb != NULL) { + + // + // Check that the client Id is valid. + // + + LfsValidateClientId( Lfcb, Lch ); + + // + // Call our common routine to perform the work. + // + + LfsFlushToLsnPriv( Lfcb, Lsn ); + } + + } finally { + + DebugUnwind( LfsFlushToLsn ); + + // + // Release the log file control block if held. + // + + LfsReleaseLch( Lch ); + + DebugTrace( -1, Dbg, "LfsFlushToLsn: Exit\n", 0 ); + } + + } except (LfsExceptionFilter( GetExceptionInformation() )) { + + Status = GetExceptionCode(); + } + + if (Status != STATUS_SUCCESS) { + + ExRaiseStatus( Status ); + } + + return; +} + + + |