419 lines
7.5 KiB
C
419 lines
7.5 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
StrucSup.c
|
||
|
||
Abstract:
|
||
|
||
This module provides support routines for creation and deletion
|
||
of Lfs structures.
|
||
|
||
Author:
|
||
|
||
Brian Andrew [BrianAn] 20-June-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "lfsprocs.h"
|
||
|
||
//
|
||
// The debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_STRUC_SUP)
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, LfsAllocateLbcb)
|
||
#pragma alloc_text(PAGE, LfsAllocateLfcb)
|
||
#pragma alloc_text(PAGE, LfsDeallocateLbcb)
|
||
#pragma alloc_text(PAGE, LfsDeallocateLfcb)
|
||
#endif
|
||
|
||
|
||
PLFCB
|
||
LfsAllocateLfcb (
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates and initializes a log file control block.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
PLFCB - A pointer to the log file control block just
|
||
allocated and initialized.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLFCB Lfcb = NULL;
|
||
ULONG Count;
|
||
PLBCB NextLbcb;
|
||
|
||
PAGED_CODE();
|
||
|
||
DebugTrace( +1, Dbg, "LfsAllocateLfcb: Entered\n", 0 );
|
||
|
||
//
|
||
// Use a try-finally to facilitate cleanup.
|
||
//
|
||
|
||
try {
|
||
|
||
//
|
||
// Allocate and zero the structure for the Lfcb.
|
||
//
|
||
|
||
Lfcb = FsRtlAllocatePool( PagedPool, sizeof( LFCB ));
|
||
|
||
//
|
||
// Zero out the structure initially.
|
||
//
|
||
|
||
RtlZeroMemory( Lfcb, sizeof( LFCB ));
|
||
|
||
//
|
||
// Initialize the log file control block.
|
||
//
|
||
|
||
Lfcb->NodeTypeCode = LFS_NTC_LFCB;
|
||
Lfcb->NodeByteSize = sizeof( LFCB );
|
||
|
||
//
|
||
// Initialize the client links.
|
||
//
|
||
|
||
InitializeListHead( &Lfcb->LchLinks );
|
||
|
||
//
|
||
// Initialize the Lbcb links.
|
||
//
|
||
|
||
InitializeListHead( &Lfcb->LbcbWorkque );
|
||
InitializeListHead( &Lfcb->LbcbActive );
|
||
|
||
//
|
||
// Initialize and allocate the spare Lbcb queue.
|
||
//
|
||
|
||
InitializeListHead( &Lfcb->SpareLbcbList );
|
||
|
||
for (Count = 0; Count < LFCB_RESERVE_LBCB_COUNT; Count++ ) {
|
||
|
||
NextLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' );
|
||
|
||
if (NextLbcb != NULL) {
|
||
|
||
InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) NextLbcb );
|
||
Lfcb->SpareLbcbCount += 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate the Lfcb synchronization event.
|
||
//
|
||
|
||
Lfcb->Sync = FsRtlAllocatePool( NonPagedPool, sizeof( LFCB_SYNC ));
|
||
|
||
ExInitializeResource( &Lfcb->Sync->Resource );
|
||
|
||
//
|
||
// Initialize the pseudo Lsn for the restart Lbcb's
|
||
//
|
||
|
||
Lfcb->NextRestartLsn = LfsLi1;
|
||
|
||
//
|
||
// Initialize the event to the signalled state.
|
||
//
|
||
|
||
KeInitializeEvent( &Lfcb->Sync->Event, NotificationEvent, TRUE );
|
||
|
||
Lfcb->Sync->UserCount = 0;
|
||
|
||
} finally {
|
||
|
||
DebugUnwind( LfsAllocateFileControlBlock );
|
||
|
||
if (AbnormalTermination()
|
||
&& Lfcb != NULL) {
|
||
|
||
LfsDeallocateLfcb( Lfcb, TRUE );
|
||
Lfcb = NULL;
|
||
}
|
||
|
||
DebugTrace( -1, Dbg, "LfsAllocateLfcb: Exit -> %08lx\n", Lfcb );
|
||
}
|
||
|
||
return Lfcb;
|
||
}
|
||
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
VOID
|
||
LfsAllocateLbcb (
|
||
IN PLFCB Lfcb,
|
||
OUT PLBCB *Lbcb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will allocate the next Lbcb. If the pool allocation fails
|
||
we will look at the private queue of Lbcb's.
|
||
|
||
Arguments:
|
||
|
||
Lfcb - Supplies a pointer to the log file control block.
|
||
|
||
Lbcb - Address to store the allocated Lbcb.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
PLBCB NewLbcb = NULL;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// If there are enough entries on the look-aside list then get one from
|
||
// there.
|
||
//
|
||
|
||
if (Lfcb->SpareLbcbCount > LFCB_RESERVE_LBCB_COUNT) {
|
||
|
||
NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
|
||
|
||
Lfcb->SpareLbcbCount -= 1;
|
||
RemoveHeadList( &Lfcb->SpareLbcbList );
|
||
|
||
//
|
||
// Otherwise try to allocate from pool.
|
||
//
|
||
|
||
} else {
|
||
|
||
NewLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' );
|
||
}
|
||
|
||
//
|
||
// If we didn't get one then look at the look-aside list.
|
||
//
|
||
|
||
if (NewLbcb == NULL) {
|
||
|
||
if (Lfcb->SpareLbcbCount != 0) {
|
||
|
||
NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
|
||
|
||
Lfcb->SpareLbcbCount -= 1;
|
||
RemoveHeadList( &Lfcb->SpareLbcbList );
|
||
|
||
} else {
|
||
|
||
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Initialize the structure.
|
||
//
|
||
|
||
RtlZeroMemory( NewLbcb, sizeof( LBCB ));
|
||
NewLbcb->NodeTypeCode = LFS_NTC_LBCB;
|
||
NewLbcb->NodeByteSize = sizeof( LBCB );
|
||
|
||
//
|
||
// Return it to the user.
|
||
//
|
||
|
||
*Lbcb = NewLbcb;
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
LfsDeallocateLbcb (
|
||
IN PLFCB Lfcb,
|
||
IN PLBCB Lbcb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will deallocate the Lbcb. If we need one for the look-aside
|
||
list we will put it there.
|
||
|
||
Arguments:
|
||
|
||
Lfcb - Supplies a pointer to the log file control block.
|
||
|
||
Lbcb - This is the Lbcb to deallocate.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Deallocate any restart area attached to this Lbcb.
|
||
//
|
||
|
||
if (FlagOn( Lbcb->LbcbFlags, LBCB_RESTART_LBCB ) &&
|
||
(Lbcb->PageHeader != NULL)) {
|
||
|
||
LfsDeallocateRestartArea( Lbcb->PageHeader );
|
||
}
|
||
|
||
//
|
||
// Put this in the Lbcb queue if it is short.
|
||
//
|
||
|
||
if (Lfcb->SpareLbcbCount < LFCB_MAX_LBCB_COUNT) {
|
||
|
||
InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) Lbcb );
|
||
Lfcb->SpareLbcbCount += 1;
|
||
|
||
//
|
||
// Otherwise just free the pool block.
|
||
//
|
||
|
||
} else {
|
||
|
||
ExFreePool( Lbcb );
|
||
}
|
||
|
||
return;
|
||
}
|