Implemented merging of free blocks.

svn path=/trunk/; revision=4144
This commit is contained in:
Eric Kohl 2003-02-13 13:59:57 +00:00
parent 493e797fa0
commit 44e85c2846
2 changed files with 156 additions and 53 deletions

View file

@ -532,7 +532,8 @@ CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
NTSTATUS NTSTATUS
CmiAddFree(PREGISTRY_HIVE RegistryHive, CmiAddFree(PREGISTRY_HIVE RegistryHive,
PCELL_HEADER FreeBlock, PCELL_HEADER FreeBlock,
BLOCK_OFFSET FreeOffset); BLOCK_OFFSET FreeOffset,
BOOLEAN MergeFreeBlocks);
NTSTATUS NTSTATUS
CmiInitHives(BOOLEAN SetUpBoot); CmiInitHives(BOOLEAN SetUpBoot);

View file

@ -743,7 +743,8 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
{ {
Status = CmiAddFree(RegistryHive, Status = CmiAddFree(RegistryHive,
FreeBlock, FreeBlock,
RegistryHive->BlockList[i]->BlockOffset + FreeOffset); RegistryHive->BlockList[i]->BlockOffset + FreeOffset,
FALSE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -1429,18 +1430,29 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
{ {
DPRINT1("ParentKey %p\n", ParentKey) DPRINT1("ParentKey %p\n", ParentKey)
ParentKey->KeyCell->NumberOfSubKeys--; ParentKey->KeyCell->NumberOfSubKeys--;
NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
CmiMarkBlockDirty(RegistryHive,
ParentKey->BlockOffset);
/* Remove the parent key's hash table */ /* Remove the parent key's hash table */
if (ParentKey->KeyCell->NumberOfSubKeys == 0) if (ParentKey->KeyCell->NumberOfSubKeys == 0)
{ {
DPRINT1("FIXME: Remove parent key hash table\n") DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
HashBlock = CmiGetBlock(RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
DPRINT1("ParentKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
CmiDestroyBlock(RegistryHive,
HashBlock,
ParentKey->KeyCell->HashTableOffset);
ParentKey->KeyCell->HashTableOffset = -1;
} }
} }
NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
CmiMarkBlockDirty(RegistryHive,
ParentKey->BlockOffset);
}
/* Destroy key cell */ /* Destroy key cell */
CmiDestroyBlock(RegistryHive, CmiDestroyBlock(RegistryHive,
SubKey->KeyCell, SubKey->KeyCell,
@ -1448,8 +1460,6 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
SubKey->BlockOffset = -1; SubKey->BlockOffset = -1;
SubKey->KeyCell = NULL; SubKey->KeyCell = NULL;
/* FIXME: Merge free blocks within the Bin */
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1652,6 +1662,8 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
CurValueCell->NameSize, CurValueCell->NameSize,
CurValueCell->Flags & REG_VALUE_NAME_PACKED)) CurValueCell->Flags & REG_VALUE_NAME_PACKED))
{ {
CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
if ((KeyCell->NumberOfValues - 1) < i) if ((KeyCell->NumberOfValues - 1) < i)
{ {
RtlCopyMemory(&ValueListCell->Values[i], RtlCopyMemory(&ValueListCell->Values[i],
@ -1664,7 +1676,6 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
} }
KeyCell->NumberOfValues -= 1; KeyCell->NumberOfValues -= 1;
CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
break; break;
} }
CmiReleaseBlock(RegistryHive, CurValueCell); CmiReleaseBlock(RegistryHive, CurValueCell);
@ -1859,9 +1870,11 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
PVOID pBlock; PVOID pBlock;
PHBIN pBin; PHBIN pBin;
DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell, VBOffset);
VERIFY_VALUE_CELL(ValueCell); VERIFY_VALUE_CELL(ValueCell);
/* First, release data: */ /* Destroy the data cell */
if (ValueCell->DataSize > 4) if (ValueCell->DataSize > 4)
{ {
pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin); pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin);
@ -1876,6 +1889,7 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
ZwQuerySystemTime((PTIME) &pBin->DateModified); ZwQuerySystemTime((PTIME) &pBin->DateModified);
} }
/* Destroy the value cell */
Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset); Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset);
/* Update time of heap */ /* Update time of heap */
@ -2047,8 +2061,12 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
{ {
NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); CmiAddFree(RegistryHive,
CmiMarkBlockDirty(RegistryHive, *pBlockOffset + BlockSize); NewBlock,
*pBlockOffset + BlockSize,
TRUE);
CmiMarkBlockDirty(RegistryHive,
*pBlockOffset + BlockSize);
} }
else if (NewBlock->CellSize < BlockSize) else if (NewBlock->CellSize < BlockSize)
{ {
@ -2091,7 +2109,8 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG), RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG),
pFree->CellSize - sizeof(ULONG)); pFree->CellSize - sizeof(ULONG));
CmiAddFree(RegistryHive, Block, Offset); /* add block to the list of free blocks */
CmiAddFree(RegistryHive, Block, Offset, TRUE);
CmiReleaseBlock(RegistryHive, Block); CmiReleaseBlock(RegistryHive, Block);
/* Update time of heap */ /* Update time of heap */
@ -2108,10 +2127,104 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
} }
static BOOLEAN
CmiMergeFree(PREGISTRY_HIVE RegistryHive,
PCELL_HEADER FreeBlock,
BLOCK_OFFSET FreeOffset)
{
BLOCK_OFFSET BlockOffset;
BLOCK_OFFSET BinOffset;
ULONG BlockSize;
ULONG BinSize;
PHBIN Bin;
LONG i;
DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
FreeBlock, FreeOffset, FreeBlock->CellSize);
CmiGetBlock(RegistryHive,
FreeOffset,
&Bin);
DPRINT("Bin %p\n", Bin);
if (Bin == NULL)
return(FALSE);
BinOffset = Bin->BlockOffset;
BinSize = Bin->BlockSize;
DPRINT("Bin %p Offset %lx Size %lx\n", Bin, BinOffset, BinSize);
for (i = 0; i < RegistryHive->FreeListSize; i++)
{
BlockOffset = RegistryHive->FreeListOffset[i];
BlockSize = RegistryHive->FreeList[i]->CellSize;
if (BlockOffset > BinOffset &&
BlockOffset < BinOffset + BinSize)
{
DPRINT("Free block: Offset %lx Size %lx\n",
BlockOffset, BlockSize);
if ((i < (RegistryHive->FreeListSize - 1)) &&
(BlockOffset + BlockSize == FreeOffset) &&
(FreeOffset + FreeBlock->CellSize == RegistryHive->FreeListOffset[i + 1]))
{
DPRINT("Merge current block with previous and next block\n");
RegistryHive->FreeList[i]->CellSize +=
(FreeBlock->CellSize + RegistryHive->FreeList[i + 1]->CellSize);
FreeBlock->CellSize = 0;
RegistryHive->FreeList[i + 1]->CellSize = 0;
if ((i + 2) < RegistryHive->FreeListSize)
{
RtlMoveMemory(&RegistryHive->FreeListOffset[i + 1],
&RegistryHive->FreeListOffset[i + 2],
sizeof(RegistryHive->FreeListOffset[0])
* (RegistryHive->FreeListSize - i - 2));
}
RegistryHive->FreeListSize--;
CmiMarkBlockDirty(RegistryHive, BlockOffset);
return(TRUE);
}
else if (BlockOffset + BlockSize == FreeOffset)
{
DPRINT("Merge current block with previous block\n");
RegistryHive->FreeList[i]->CellSize += FreeBlock->CellSize;
FreeBlock->CellSize = 0;
CmiMarkBlockDirty(RegistryHive, BlockOffset);
return(TRUE);
}
else if (FreeOffset + FreeBlock->CellSize == BlockOffset)
{
DPRINT("Merge current block with next block\n");
FreeBlock->CellSize += RegistryHive->FreeList[i]->CellSize;
RegistryHive->FreeList[i]->CellSize = 0;
RegistryHive->FreeList[i] = FreeBlock;
RegistryHive->FreeListOffset[i] = FreeOffset;
CmiMarkBlockDirty(RegistryHive, FreeOffset);
return(TRUE);
}
}
}
return(FALSE);
}
NTSTATUS NTSTATUS
CmiAddFree(PREGISTRY_HIVE RegistryHive, CmiAddFree(PREGISTRY_HIVE RegistryHive,
PCELL_HEADER FreeBlock, PCELL_HEADER FreeBlock,
BLOCK_OFFSET FreeOffset) BLOCK_OFFSET FreeOffset,
BOOLEAN MergeFreeBlocks)
{ {
PCELL_HEADER *tmpList; PCELL_HEADER *tmpList;
BLOCK_OFFSET *tmpListOffset; BLOCK_OFFSET *tmpListOffset;
@ -2122,67 +2235,58 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive,
assert(RegistryHive); assert(RegistryHive);
assert(FreeBlock); assert(FreeBlock);
DPRINT("FreeBlock %.08x FreeOffset %.08x\n", DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n",
FreeBlock, FreeOffset); FreeBlock, FreeOffset);
DPRINT("\n");
/* Merge free blocks */
if (MergeFreeBlocks == TRUE)
{
if (CmiMergeFree(RegistryHive, FreeBlock, FreeOffset))
return(STATUS_SUCCESS);
}
if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax) if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax)
{ {
DPRINT("\n");
tmpList = ExAllocatePool(PagedPool, tmpList = ExAllocatePool(PagedPool,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32)); sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32));
DPRINT("\n");
if (tmpList == NULL) if (tmpList == NULL)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
DPRINT("\n");
tmpListOffset = ExAllocatePool(PagedPool, tmpListOffset = ExAllocatePool(PagedPool,
sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32)); sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32));
DPRINT("\n");
if (tmpListOffset == NULL) if (tmpListOffset == NULL)
{ {
ExFreePool(tmpList); ExFreePool(tmpList);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
DPRINT("\n");
if (RegistryHive->FreeListMax) if (RegistryHive->FreeListMax)
{ {
DPRINT("\n");
RtlMoveMemory(tmpList, RtlMoveMemory(tmpList,
RegistryHive->FreeList, RegistryHive->FreeList,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
DPRINT("\n");
RtlMoveMemory(tmpListOffset, RtlMoveMemory(tmpListOffset,
RegistryHive->FreeListOffset, RegistryHive->FreeListOffset,
sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax)); sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax));
DPRINT("\n");
ExFreePool(RegistryHive->FreeList); ExFreePool(RegistryHive->FreeList);
DPRINT("\n");
ExFreePool(RegistryHive->FreeListOffset); ExFreePool(RegistryHive->FreeListOffset);
DPRINT("\n");
} }
DPRINT("\n");
RegistryHive->FreeList = tmpList; RegistryHive->FreeList = tmpList;
RegistryHive->FreeListOffset = tmpListOffset; RegistryHive->FreeListOffset = tmpListOffset;
RegistryHive->FreeListMax += 32; RegistryHive->FreeListMax += 32;
DPRINT("\n");
} }
DPRINT("\n");
/* Add new offset to free list, maintaining list in ascending order */ /* Add new offset to free list, maintaining list in ascending order */
if ((RegistryHive->FreeListSize == 0) if ((RegistryHive->FreeListSize == 0)
|| (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset)) || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset))
{ {
DPRINT("\n");
/* Add to end of list */ /* Add to end of list */
RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock; RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock;
RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset; RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset;
} }
else if (RegistryHive->FreeListOffset[0] > FreeOffset) else if (RegistryHive->FreeListOffset[0] > FreeOffset)
{ {
DPRINT("\n");
/* Add to begin of list */ /* Add to begin of list */
RtlMoveMemory(&RegistryHive->FreeList[1], RtlMoveMemory(&RegistryHive->FreeList[1],
&RegistryHive->FreeList[0], &RegistryHive->FreeList[0],
@ -2196,7 +2300,6 @@ DPRINT("\n");
} }
else else
{ {
DPRINT("\n");
/* Search where to insert */ /* Search where to insert */
minInd = 0; minInd = 0;
maxInd = RegistryHive->FreeListSize - 1; maxInd = RegistryHive->FreeListSize - 1;
@ -2220,7 +2323,6 @@ DPRINT("\n");
RegistryHive->FreeListOffset[maxInd] = FreeOffset; RegistryHive->FreeListOffset[maxInd] = FreeOffset;
RegistryHive->FreeListSize++; RegistryHive->FreeListSize++;
} }
DPRINT("\n");
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2248,7 +2350,7 @@ CmiGetBlock(PREGISTRY_HIVE RegistryHive,
pBin = RegistryHive->BlockList[BlockOffset / 4096]; pBin = RegistryHive->BlockList[BlockOffset / 4096];
if (ppBin) if (ppBin)
*ppBin = pBin; *ppBin = pBin;
return ((PVOID) ((ULONG_PTR) pBin + (BlockOffset - pBin->BlockOffset))); return((PVOID)((ULONG_PTR)pBin + (BlockOffset - pBin->BlockOffset)));
} }
} }