/*++ Copyright (c) 1991 Microsoft Corporation Module Name: hivefree.c Abstract: Hive free code Author: Bryan M. Willman (bryanwi) 30-Mar-92 Environment: Revision History: Dragos C. Sambotin (dragoss) 25-Jan-99 Implementation of bin-size chunk loading of hives. --*/ #include "cmp.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE,HvFreeHive) #pragma alloc_text(PAGE,HvFreeHivePartial) #endif // Dragos: Modified functions 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); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive(%ws) :\n", Hive->BaseBlock->FileName)); // // 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); VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address); 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)HBIN_BASE(Me->BinAddress), FreeBin->Size); } else if(Me->BinAddress & HMAP_INPAGEDPOOL) { // // The bin has been freed, but quota is still charged. // Since the hive is being freed, the quota must be // returned here. // CmpReleaseGlobalQuota(FreeBin->Size); } CmpFree(FreeBin, sizeof(FREE_HBIN)); } else { if( Me->BinAddress & HMAP_INPAGEDPOOL ) { ASSERT( Me->BinAddress & HMAP_INPAGEDPOOL ); Bin = (PHBIN)HBIN_BASE(Me->BinAddress); Address += HvpGetBinMemAlloc(Hive,Bin,Type); #if 0 // // Make sure that the next bin in the list is // actually the start of an alloc before freeing it // if (Address < Length) { TempMe = HvpGetCellMap(Hive, Address); VALIDATE_CELL_MAP(__LINE__,TempMe,Hive,Address); ASSERT(TempMe->BinAddress & HMAP_NEWALLOC); } #endif #if DBG if( Type == Stable ) { CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"HvFreeHive: BinAddress = 0x%p\t Size = 0x%lx\n", Bin, HvpGetBinMemAlloc(Hive,Bin,Type))); } #endif // // free the actual bin only if it is allocated from paged pool // if(HvpGetBinMemAlloc(Hive,Bin,Type)) { CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type)); } } else { // // bin was mapped into view; advance carefully // Address += HBLOCK_SIZE; } } } 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; } CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BIN_MAP,"\n")); // // Free the base block // (Hive->Free)(Hive->BaseBlock,Hive->BaseBlockAlloc); Hive->BaseBlock = NULL; // // Free the dirty vector // if (Hive->DirtyVector.Buffer != NULL) { CmpFree((PVOID)(Hive->DirtyVector.Buffer), Hive->DirtyAlloc); } HvpFreeHiveFreeDisplay(Hive); 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)); VALIDATE_CELL_MAP(__LINE__,Me,Hive,Address + (Type*HCELL_TYPE_MASK)); if (Me->BinAddress & HMAP_DISCARDABLE) { FreeBin = (PFREE_HBIN)Me->BlockAddress; if (FreeBin->Flags & FREE_HBIN_DISCARDABLE) { CmpFree((PVOID)HBIN_BASE(Me->BinAddress), 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. // if( Me->BinAddress & HMAP_INPAGEDPOOL) { // // we charge quota only for bins in paged-pool // CmpReleaseGlobalQuota(FreeBin->Size); } } RemoveEntryList(&FreeBin->ListEntry); Address += FreeBin->Size; CmpFree(FreeBin, sizeof(FREE_HBIN)); } else { Bin = (PHBIN)HBIN_BASE(Me->BinAddress); Address += HvpGetBinMemAlloc(Hive,Bin,Type); if( Me->BinAddress & HMAP_INPAGEDPOOL && HvpGetBinMemAlloc(Hive,Bin,Type) ) { // // free the bin only if it is allocated from paged pool // CmpFree(Bin, HvpGetBinMemAlloc(Hive,Bin,Type)); } } } 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); // // update hysteresis (eventually queue work item) // if( Type == Stable) { CmpUpdateSystemHiveHysteresis(Hive,(Start&(~HCELL_TYPE_MASK)),Hive->Storage[Type].Length); } Hive->Storage[Type].Length = (Start&(~HCELL_TYPE_MASK)); 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); } HvpAdjustHiveFreeDisplay(Hive,Hive->Storage[Type].Length,Type); return; }