PLBCB LfsGetLbcb ( IN PLFCB Lfcb ) /*++ Routine Description: This routine is called to add a Lbcb to the active queue. Arguments: Lfcb - This is the file control block for the log file. Return Value: PLBCB - Pointer to the Lbcb allocated. --*/ { PLBCB Lbcb = NULL; PVOID PageHeader; PBCB PageHeaderBcb = NULL; BOOLEAN WrappedOrUsaError; PAGED_CODE(); LfsDebugTrace( +1, Dbg, "LfsGetLbcb: Entered\n", 0 ); LfsDebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); // // Use a try-finally to facilitate cleanup. // try { // // Pin the desired record page. // LfsPreparePinWriteData( Lfcb, Lfcb->NextLogPage, (ULONG)Lfcb->LogPageSize, &PageHeader, &PageHeaderBcb ); // // Put our signature into the page so we won't fail if we // see a previous 'BAAD' signature. // *((PULONG) PageHeader) = LFS_SIGNATURE_RECORD_PAGE_ULONG; // // Now allocate an Lbcb. // LfsAllocateLbcb( Lfcb, &Lbcb ); // // If we are at the beginning of the file we test that the // sequence number won't wrap to 0. // if (!FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN | LFCB_REUSE_TAIL ) && ( Lfcb->NextLogPage == Lfcb->FirstLogPage )) { Lfcb->SeqNumber = Lfcb->SeqNumber + 1; // // If the sequence number is going from 0 to 1, then // this is the first time the log file has wrapped. We want // to remember this because it means that we can now do // large spiral writes. // if (Int64ShllMod32( Lfcb->SeqNumber, Lfcb->FileDataBits ) == 0) { LfsDebugTrace( 0, Dbg, "Log sequence number about to wrap: Lfcb -> %08lx\n", Lfcb ); KeBugCheck( FILE_SYSTEM ); } // // If this number is greater or equal to the wrap sequence number in // the Lfcb, set the wrap flag in the Lbcb. // if (!FlagOn( Lfcb->Flags, LFCB_LOG_WRAPPED ) && ( Lfcb->SeqNumber >= Lfcb->SeqNumberForWrap )) { SetFlag( Lbcb->LbcbFlags, LBCB_LOG_WRAPPED ); SetFlag( Lfcb->Flags, LFCB_LOG_WRAPPED ); } } // // Now initialize the rest of the Lbcb fields. // Lbcb->FileOffset = Lfcb->NextLogPage; Lbcb->SeqNumber = Lfcb->SeqNumber; Lbcb->BufferOffset = Lfcb->LogPageDataOffset; // // Store the next page in the Lfcb. // LfsNextLogPageOffset( Lfcb, Lfcb->NextLogPage, &Lfcb->NextLogPage, &WrappedOrUsaError ); Lbcb->Length = Lfcb->LogPageSize; Lbcb->PageHeader = PageHeader; Lbcb->LogPageBcb = PageHeaderBcb; Lbcb->ResourceThread = ExGetCurrentResourceThread(); // // If we are reusing a previous page then set a flag in // the Lbcb to indicate that we should flush a copy // first. // if (FlagOn( Lfcb->Flags, LFCB_REUSE_TAIL )) { SetFlag( Lbcb->LbcbFlags, LBCB_FLUSH_COPY ); ClearFlag( Lfcb->Flags, LFCB_REUSE_TAIL ); (ULONG)Lbcb->BufferOffset = Lfcb->ReusePageOffset; Lbcb->Flags = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Flags; Lbcb->LastLsn = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Copy.LastLsn; Lbcb->LastEndLsn = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Header.Packed.LastEndLsn; } // // Put the Lbcb on the active queue // InsertTailList( &Lfcb->LbcbActive, &Lbcb->ActiveLinks ); SetFlag( Lbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE ); } finally { DebugUnwind( LfsGetLbcb ); // // If an error occurred, we need to clean up any blocks which // have not been added to the active queue. // if (AbnormalTermination()) { if (Lbcb != NULL) { LfsDeallocateLbcb( Lfcb, Lbcb ); Lbcb = NULL; } // // Unpin the system page if pinned. // if (PageHeaderBcb != NULL) { CcUnpinData( PageHeaderBcb ); } } LfsDebugTrace( -1, Dbg, "LfsGetLbcb: Exit\n", 0 ); } return Lbcb; }
VOID LfsDeallocateLfcb ( IN PLFCB Lfcb, IN BOOLEAN CompleteTeardown ) /*++ Routine Description: This routine releases the resources associated with a log file control block. Arguments: Lfcb - Supplies a pointer to the log file control block. CompleteTeardown - Indicates if we are to completely remove this Lfcb. Return Value: None --*/ { PLBCB NextLbcb; PAGED_CODE(); DebugTrace( +1, Dbg, "LfsDeallocateLfcb: Entered\n", 0 ); DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); // // Check that there are no buffer blocks. // ASSERT( IsListEmpty( &Lfcb->LbcbActive )); ASSERT( IsListEmpty( &Lfcb->LbcbWorkque )); // // Check that we have no clients. // ASSERT( IsListEmpty( &Lfcb->LchLinks )); // // If there is a restart area we deallocate it. // if (Lfcb->RestartArea != NULL) { LfsDeallocateRestartArea( Lfcb->RestartArea ); } // // If there are any of the tail Lbcb's, deallocate them now. // if (Lfcb->ActiveTail != NULL) { LfsDeallocateLbcb( Lfcb, Lfcb->ActiveTail ); Lfcb->ActiveTail = NULL; } if (Lfcb->PrevTail != NULL) { LfsDeallocateLbcb( Lfcb, Lfcb->PrevTail ); Lfcb->PrevTail = NULL; } // // Only do the following if we are to remove the Lfcb completely. // if (CompleteTeardown) { // // If there is a resource structure we deallocate it. // if (Lfcb->Sync != NULL) { ExDeleteResource( &Lfcb->Sync->Resource ); ExFreePool( Lfcb->Sync ); } } // // Deallocate all of the spare Lbcb's. // while (!IsListEmpty( &Lfcb->SpareLbcbList )) { NextLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink; RemoveHeadList( &Lfcb->SpareLbcbList ); ExFreePool( NextLbcb ); } // // Discard the Lfcb structure. // ExFreePool( Lfcb ); DebugTrace( -1, Dbg, "LfsDeallocateLfcb: Exit\n", 0 ); return; }