summaryrefslogtreecommitdiffstats
path: root/private/ntos/lfs/write.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/lfs/write.c
downloadNT4.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.c475
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;
+}
+
+
+