252 lines
6.2 KiB
C
252 lines
6.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
hivefree.c
|
||
|
||
Abstract:
|
||
|
||
Hive free code
|
||
|
||
Author:
|
||
|
||
Bryan M. Willman (bryanwi) 30-Mar-92
|
||
|
||
Environment:
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "cmp.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,HvFreeHive)
|
||
#pragma alloc_text(PAGE,HvFreeHivePartial)
|
||
#endif
|
||
|
||
|
||
VOID
|
||
HvFreeHive(
|
||
PHHIVE Hive
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Free all of the pieces of a hive.
|
||
|
||
Arguments:
|
||
|
||
Hive - supplies a pointer to hive control structure for hive to free.
|
||
this structure itself will NOT be freed, but everything it
|
||
points to will.
|
||
|
||
Return Value:
|
||
|
||
NONE.
|
||
|
||
--*/
|
||
{
|
||
PHMAP_DIRECTORY Dir;
|
||
PHMAP_ENTRY Me;
|
||
HCELL_INDEX Address;
|
||
ULONG Type;
|
||
ULONG Length;
|
||
PHBIN Bin;
|
||
ULONG Tables;
|
||
PFREE_HBIN FreeBin;
|
||
|
||
ASSERT(Hive->Flat == FALSE);
|
||
ASSERT(Hive->ReadOnly == FALSE);
|
||
ASSERT(Stable == 0);
|
||
ASSERT(Volatile == 1);
|
||
|
||
//
|
||
// Iterate through both types of storage
|
||
//
|
||
for (Type = 0; Type <= Volatile; Type++) {
|
||
|
||
Address = HCELL_TYPE_MASK * Type;
|
||
Length = Hive->Storage[Type].Length + (HCELL_TYPE_MASK * Type);
|
||
|
||
if (Length > (HCELL_TYPE_MASK * Type)) {
|
||
|
||
//
|
||
// Sweep through bin set
|
||
//
|
||
do {
|
||
Me = HvpGetCellMap(Hive, Address);
|
||
ASSERT(Me != NULL);
|
||
if (Me->BinAddress & HMAP_DISCARDABLE) {
|
||
//
|
||
// hbin is either discarded or discardable, check the tombstone
|
||
//
|
||
FreeBin = (PFREE_HBIN)Me->BlockAddress;
|
||
Address += FreeBin->Size;
|
||
if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) {
|
||
CmpFree((PHBIN)(Me->BinAddress & HMAP_BASE), FreeBin->Size);
|
||
}
|
||
CmpFree(FreeBin, sizeof(FREE_HBIN));
|
||
} else {
|
||
Bin = (PHBIN)(Me->BinAddress & HMAP_BASE);
|
||
Address += Bin->MemAlloc;
|
||
#if DBG
|
||
//
|
||
// Make sure that the next bin in the list is
|
||
// actually the start of an alloc before freeing it
|
||
//
|
||
if (Address < Length) {
|
||
Me = HvpGetCellMap(Hive, Address);
|
||
ASSERT(Me->BinAddress & HMAP_NEWALLOC);
|
||
}
|
||
#endif
|
||
CmpFree(Bin, Bin->MemAlloc);
|
||
}
|
||
|
||
} while (Address < Length);
|
||
|
||
//
|
||
// Free map table storage
|
||
//
|
||
ASSERT(Hive->Storage[Type].Length != (HCELL_TYPE_MASK * Type));
|
||
Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE)-1) / HTABLE_SLOTS;
|
||
Dir = Hive->Storage[Type].Map;
|
||
HvpFreeMap(Hive, Dir, 0, Tables);
|
||
|
||
if (Tables > 0) {
|
||
CmpFree(Hive->Storage[Type].Map, sizeof(HMAP_DIRECTORY)); // free dir if it exists
|
||
}
|
||
}
|
||
Hive->Storage[Type].Length = 0;
|
||
}
|
||
|
||
//
|
||
// Free the base block
|
||
//
|
||
(Hive->Free)(Hive->BaseBlock, sizeof(HBASE_BLOCK));
|
||
Hive->BaseBlock = NULL;
|
||
|
||
//
|
||
// Free the dirty vector
|
||
//
|
||
if (Hive->DirtyVector.Buffer != NULL) {
|
||
CmpFree((PVOID)(Hive->DirtyVector.Buffer), Hive->DirtyAlloc);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
HvFreeHivePartial(
|
||
PHHIVE Hive,
|
||
HCELL_INDEX Start,
|
||
HSTORAGE_TYPE Type
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Free the memory and associated maps for the end of a hive
|
||
starting at Start. The baseblock, hive, etc will not be touched.
|
||
|
||
Arguments:
|
||
|
||
Hive - supplies a pointer to hive control structure for hive to
|
||
partially free.
|
||
|
||
Start - HCELL_INDEX of first bin to free, will free from this
|
||
bin (inclusive) to the end of the hives stable storage.
|
||
|
||
Type - Type of storage (Stable or Volatile) to be freed.
|
||
|
||
Return Value:
|
||
|
||
NONE.
|
||
|
||
--*/
|
||
{
|
||
PHMAP_DIRECTORY Dir;
|
||
PHMAP_ENTRY Me;
|
||
HCELL_INDEX Address;
|
||
ULONG StartTable;
|
||
ULONG Length;
|
||
PHBIN Bin;
|
||
ULONG Tables;
|
||
ULONG FirstBit;
|
||
ULONG LastBit;
|
||
PFREE_HBIN FreeBin;
|
||
|
||
ASSERT(Hive->Flat == FALSE);
|
||
ASSERT(Hive->ReadOnly == FALSE);
|
||
|
||
Address = Start;
|
||
Length = Hive->Storage[Type].Length;
|
||
ASSERT(Address <= Length);
|
||
|
||
if (Address == Length) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Sweep through bin set
|
||
//
|
||
do {
|
||
Me = HvpGetCellMap(Hive, Address + (Type*HCELL_TYPE_MASK));
|
||
ASSERT(Me != NULL);
|
||
if (Me->BinAddress & HMAP_DISCARDABLE) {
|
||
FreeBin = (PFREE_HBIN)Me->BlockAddress;
|
||
if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) {
|
||
CmpFree((PVOID)(Me->BinAddress & HMAP_BASE), FreeBin->Size);
|
||
} else {
|
||
//
|
||
// The bin has been freed, but quota is still charged.
|
||
// Since the file will now shrink, the quota must be
|
||
// returned here.
|
||
//
|
||
CmpReleaseGlobalQuota(FreeBin->Size);
|
||
}
|
||
RemoveEntryList(&FreeBin->ListEntry);
|
||
Address += FreeBin->Size;
|
||
CmpFree(FreeBin, sizeof(FREE_HBIN));
|
||
|
||
} else {
|
||
Bin = (PHBIN)(Me->BinAddress & HMAP_BASE);
|
||
|
||
Address += Bin->MemAlloc;
|
||
CmpFree(Bin, Bin->MemAlloc);
|
||
}
|
||
} while (Address < Length);
|
||
|
||
//
|
||
// Free map table storage
|
||
//
|
||
Tables = (((Hive->Storage[Type].Length) / HBLOCK_SIZE) - 1) / HTABLE_SLOTS;
|
||
Dir = Hive->Storage[Type].Map;
|
||
if (Start > 0) {
|
||
StartTable = ((Start-1) / HBLOCK_SIZE) / HTABLE_SLOTS;
|
||
} else {
|
||
StartTable = (ULONG)-1;
|
||
}
|
||
HvpFreeMap(Hive, Dir, StartTable+1, Tables);
|
||
|
||
Hive->Storage[Type].Length = Start;
|
||
|
||
if (Type==Stable) {
|
||
//
|
||
// Clear dirty vector for data past Hive->Storage[Stable].Length
|
||
//
|
||
FirstBit = Start / HSECTOR_SIZE;
|
||
LastBit = Hive->DirtyVector.SizeOfBitMap;
|
||
ASSERT(Hive->DirtyCount == RtlNumberOfSetBits(&Hive->DirtyVector));
|
||
RtlClearBits(&Hive->DirtyVector, FirstBit, LastBit-FirstBit);
|
||
Hive->DirtyCount = RtlNumberOfSetBits(&Hive->DirtyVector);
|
||
}
|
||
|
||
return;
|
||
}
|