From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/lfs/lsnsup.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 private/ntos/lfs/lsnsup.c (limited to 'private/ntos/lfs/lsnsup.c') diff --git a/private/ntos/lfs/lsnsup.c b/private/ntos/lfs/lsnsup.c new file mode 100644 index 000000000..429ef45b0 --- /dev/null +++ b/private/ntos/lfs/lsnsup.c @@ -0,0 +1,316 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + LsnSup.c + +Abstract: + + This module implements support for manipulating Lsn's. + +Author: + + Brian Andrew [BrianAn] 20-June-1991 + +Revision History: + +--*/ + +#include "lfsprocs.h" + +// +// The debug trace level +// + +#define Dbg (DEBUG_TRACE_LSN_SUP) + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, LfsFindNextLsn) +#pragma alloc_text(PAGE, LfsLsnFinalOffset) +#endif + + +VOID +LfsLsnFinalOffset ( + IN PLFCB Lfcb, + IN LSN Lsn, + IN ULONG DataLength, + OUT PLONGLONG FinalOffset + ) + +/*++ + +Routine Description: + + This routine will compute the final offset of the last byte of the log + record. It does this by computing how many bytes are on the current + page and then computing how many more pages will be needed. + +Arguments: + + Lfcb - This is the file control block for the log file. + + Lsn - This is the log record being considered. + + DataLength - This is the length of the data for this log record. We will add the + header length here. + + FinalOffset - Address to store the result. + +Return Value: + + None. + +--*/ + +{ + ULONG RemainingPageBytes; + ULONG PageOffset; + + PAGED_CODE(); + + DebugTrace( +1, Dbg, "LfsLsnFinalOffset: Entered\n", 0 ); + DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); + DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn.LowPart ); + DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn.HighPart ); + DebugTrace( 0, Dbg, "DataLength -> %08lx\n", DataLength ); + + // + // We compute the starting log page file offset, the number of bytes + // remaining in the current log page and the position on this page + // before any data bytes. + // + + LfsTruncateLsnToLogPage( Lfcb, Lsn, FinalOffset ); + + PageOffset = LfsLsnToPageOffset( Lfcb, Lsn ); + + RemainingPageBytes = (ULONG)Lfcb->LogPageSize - PageOffset; + + PageOffset -= 1; + + // + // Add the length of the header. + // + + DataLength += Lfcb->RecordHeaderLength; + + // + // If this Lsn is contained in this log page we are done. + // Otherwise we need to walk through several log pages. + // + + if (DataLength > RemainingPageBytes) { + + DataLength -= RemainingPageBytes; + + RemainingPageBytes = (ULONG)Lfcb->LogPageDataSize; + + PageOffset = (ULONG)Lfcb->LogPageDataOffset - 1; + + while (TRUE) { + + BOOLEAN Wrapped; + + LfsNextLogPageOffset( Lfcb, *FinalOffset, FinalOffset, &Wrapped ); + + // + // We are done if the remaining bytes fit on this page. + // + + if (DataLength <= RemainingPageBytes) { + + break; + } + + DataLength -= RemainingPageBytes; + } + } + + // + // We add the remaining bytes to our starting position on this page + // and then add that value to the file offset of this log page. + // + + *(PULONG)FinalOffset += (DataLength + PageOffset); + + DebugTrace( 0, Dbg, "FinalOffset (Low) -> %08lx\n", LogPageFileOffset.LowPart ); + DebugTrace( 0, Dbg, "FinalOffset (High) -> %08lx\n", LogPageFileOffset.HighPart ); + DebugTrace( -1, Dbg, "LfsLsnFinalOffset: Exit\n", 0 ); + + return; +} + + +BOOLEAN +LfsFindNextLsn ( + IN PLFCB Lfcb, + IN PLFS_RECORD_HEADER RecordHeader, + OUT PLSN Lsn + ) + +/*++ + +Routine Description: + + This routine takes as a starting point the log record header of an + Lsn in the log file. It searches for the next Lsn in the file and + returns that value in the 'Lsn' argument. The boolean return value + indicates whether there is another Lsn in the file. + +Arguments: + + Lfcb - This is the file control block for the log file. + + RecordHeader - This is the log record for the Lsn starting point. + + Lsn - This supplies the address to store the next Lsn, if found. + +Return Value: + + BOOLEAN - Indicates whether the next Lsn was found. + +--*/ + +{ + BOOLEAN FoundNextLsn; + + LONGLONG LsnOffset; + LONGLONG EndOfLogRecord; + LONGLONG LogHeaderOffset; + + LONGLONG SequenceNumber; + + PLFS_RECORD_PAGE_HEADER LogRecordPage; + PBCB LogRecordPageBcb; + BOOLEAN UsaError; + + PAGED_CODE(); + + DebugTrace( +1, Dbg, "LfsFindNextLsn: Entered\n", 0 ); + DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); + DebugTrace( 0, Dbg, "Record Header -> %08lx\n", RecordHeader ); + + LogRecordPageBcb = NULL; + FoundNextLsn = FALSE; + + // + // Use a try-finally to facilitate cleanup. + // + + try { + + // + // Find the file offset of the log page which contains the end + // of the log record for this Lsn. + // + + LsnOffset = LfsLsnToFileOffset( Lfcb, RecordHeader->ThisLsn ); + + LfsLsnFinalOffset( Lfcb, + RecordHeader->ThisLsn, + RecordHeader->ClientDataLength, + &EndOfLogRecord ); + + LfsTruncateOffsetToLogPage( Lfcb, EndOfLogRecord, &LogHeaderOffset ); + + // + // Remember the sequence number for this page. + // + + SequenceNumber = LfsLsnToSeqNumber( Lfcb, RecordHeader->ThisLsn ); + + // + // Remember if we wrapped. + // + + if ( EndOfLogRecord <= LsnOffset ) { //**** xxLeq( EndOfLogRecord, LsnOffset ) + + SequenceNumber = SequenceNumber + 1; //**** xxAdd( SequenceNumber, LfsLi1 ); + } + + // + // Pin the log page header for this page. + // + + LfsPinOrMapData( Lfcb, + LogHeaderOffset, + (ULONG)Lfcb->LogPageSize, + FALSE, + FALSE, + FALSE, + &UsaError, + (PVOID *)&LogRecordPage, + &LogRecordPageBcb ); + + // + // If the Lsn we were given was not the last Lsn on this page, then + // the starting offset for the next Lsn is on a quad word boundary + // following the last file offset for the current Lsn. Otherwise + // the file offset is the start of the data on the next page. + // + + if ( RecordHeader->ThisLsn.QuadPart == LogRecordPage->Copy.LastLsn.QuadPart ) { //**** xxEql( RecordHeader->ThisLsn, LogRecordPage->Copy.LastLsn ) + + BOOLEAN Wrapped; + + LfsNextLogPageOffset( Lfcb, + LogHeaderOffset, + &LogHeaderOffset, + &Wrapped ); + + LsnOffset = LogHeaderOffset + Lfcb->LogPageDataOffset; //**** xxAdd( LogHeaderOffset, Lfcb->LogPageDataOffset ); + + // + // If we wrapped, we need to increment the sequence number. + // + + if (Wrapped) { + + SequenceNumber = SequenceNumber + 1; //**** xxAdd( SequenceNumber, LfsLi1 ); + } + + } else { + + LiQuadAlign( EndOfLogRecord, &LsnOffset ); + } + + // + // Compute the Lsn based on the file offset and the sequence count. + // + + Lsn->QuadPart = LfsFileOffsetToLsn( Lfcb, LsnOffset, SequenceNumber ); + + // + // If this Lsn is within the legal range for the file, we return TRUE. + // Otherwise FALSE indicates that there are no more Lsn's. + // + + if (LfsIsLsnInFile( Lfcb, *Lsn )) { + + FoundNextLsn = TRUE; + } + + } finally { + + DebugUnwind( LfsFindNextLsn ); + + // + // Unpin the log page header if held. + // + + if (LogRecordPageBcb != NULL) { + + CcUnpinData( LogRecordPageBcb ); + } + + DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); + DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); + DebugTrace( -1, Dbg, "LfsFindNextLsn: Exit -> %08x\n", FoundNextLsn ); + } + + return FoundNextLsn; +} + -- cgit v1.2.3