Use ERESOURCE instead of spinlock to protect the hive list.

Use worker thread to run hive flush routine at dispatch level.
 - Changes by Hartmut Birr!

Delete a key's hash block when the key is deleted.
Update pointers and offsets in a key object when the key cell is deleted.

svn path=/trunk/; revision=4134
This commit is contained in:
Eric Kohl 2003-02-10 21:24:45 +00:00
parent 0430d6bf60
commit 848ea5c2e0
4 changed files with 121 additions and 68 deletions

View file

@ -332,7 +332,7 @@ extern POBJECT_TYPE CmiKeyType;
extern KSPIN_LOCK CmiKeyListLock;
extern LIST_ENTRY CmiHiveListHead;
extern KSPIN_LOCK CmiHiveListLock;
extern ERESOURCE CmiHiveListLock;
VOID

View file

@ -143,6 +143,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
CreateOptions);
if (!NT_SUCCESS(Status))
{
/* Release hive lock */
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
ObDereferenceObject(KeyObject);
ObDereferenceObject(Object);
@ -171,6 +172,8 @@ NtCreateKey(OUT PHANDLE KeyHandle,
CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
VERIFY_KEY_OBJECT(KeyObject);
/* Release hive lock */
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
@ -180,8 +183,6 @@ NtCreateKey(OUT PHANDLE KeyHandle,
if (Disposition)
*Disposition = REG_CREATED_NEW_KEY;
VERIFY_KEY_OBJECT(KeyObject);
CmiSyncHives();
return Status;
@ -197,6 +198,7 @@ NtDeleteKey(IN HANDLE KeyHandle)
DPRINT("KeyHandle %x\n", KeyHandle);
/* Verify that the handle is valid and is a registry key */
CHECKPOINT1;
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_WRITE,
CmiKeyType,
@ -205,28 +207,32 @@ NtDeleteKey(IN HANDLE KeyHandle)
NULL);
if (!NT_SUCCESS(Status))
{
CHECKPOINT1;
return(Status);
}
CHECKPOINT1;
/* Acquire hive lock */
ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
CHECKPOINT1;
VERIFY_KEY_OBJECT(KeyObject);
/* Set the marked for delete bit in the key object */
KeyObject->Flags |= KO_MARKED_FOR_DELETE;
CHECKPOINT1;
/* Release hive lock */
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
/* Dereference the object */
ObDereferenceObject(KeyObject);
if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
ObDereferenceObject(KeyObject);
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
/*
* Note:

View file

@ -809,7 +809,6 @@ CmiCreateRegistryHive(PWSTR Filename,
BOOLEAN CreateNew)
{
PREGISTRY_HIVE Hive;
KIRQL oldlvl;
NTSTATUS Status;
DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename);
@ -851,10 +850,14 @@ CmiCreateRegistryHive(PWSTR Filename,
ExInitializeResourceLite(&Hive->HiveResource);
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
/* Add the new hive to the hive list */
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
InsertHeadList(&CmiHiveListHead, &Hive->HiveList);
KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
VERIFY_REGISTRY_HIVE(Hive);
@ -869,12 +872,14 @@ CmiCreateRegistryHive(PWSTR Filename,
NTSTATUS
CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
{
KIRQL oldlvl;
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
/* Remove hive from hive list */
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
RemoveEntryList(&RegistryHive->HiveList);
KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
/* FIXME: Remove attached keys and values */
@ -1385,46 +1390,56 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
DPRINT1("CmiRemoveSubKey() called\n");
/* Remove the key from the parent key's hash block */
HashBlock = CmiGetBlock(RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock != NULL)
if (ParentKey->KeyCell->HashTableOffset != -1)
{
CmiRemoveKeyFromHashTable(RegistryHive,
HashBlock,
SubKey->BlockOffset);
CmiMarkBlockDirty(RegistryHive,
ParentKey->KeyCell->HashTableOffset);
DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
HashBlock = CmiGetBlock(RegistryHive,
ParentKey->KeyCell->HashTableOffset,
NULL);
DPRINT1("ParentKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
CmiRemoveKeyFromHashTable(RegistryHive,
HashBlock,
SubKey->BlockOffset);
CmiMarkBlockDirty(RegistryHive,
ParentKey->KeyCell->HashTableOffset);
}
}
/* Remove the key's hash block */
DPRINT1("HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
if (SubKey->KeyCell->HashTableOffset != 0)
if (SubKey->KeyCell->HashTableOffset != -1)
{
DPRINT1("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
HashBlock = CmiGetBlock(RegistryHive,
SubKey->KeyCell->HashTableOffset,
NULL);
DPRINT1("HashBlock %p\n", HashBlock)
DPRINT1("SubKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL)
{
CmiDestroyBlock(RegistryHive,
HashBlock,
SubKey->KeyCell->HashTableOffset);
SubKey->KeyCell->HashTableOffset = -1;
}
SubKey->KeyCell->HashTableOffset = 0;
}
CHECKPOINT1;
/* Remove the key from the parent key's hash block */
ParentKey->KeyCell->NumberOfSubKeys--;
CmiMarkBlockDirty(RegistryHive,
ParentKey->BlockOffset);
/* Decrement the number of the parent key's sub keys */
if (ParentKey != NULL)
{
DPRINT1("ParentKey %p\n", ParentKey)
ParentKey->KeyCell->NumberOfSubKeys--;
NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
CmiMarkBlockDirty(RegistryHive,
ParentKey->BlockOffset);
}
CHECKPOINT1;
/* Destroy key cell */
CmiDestroyBlock(RegistryHive,
SubKey->KeyCell,
SubKey->BlockOffset);
SubKey->BlockOffset = -1;
SubKey->KeyCell = NULL;
return(STATUS_SUCCESS);
}

View file

@ -1,4 +1,4 @@
/* $Id: registry.c,v 1.82 2003/02/09 11:57:14 ekohl Exp $
/* $Id: registry.c,v 1.83 2003/02/10 21:24:45 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -35,7 +35,7 @@ PREGISTRY_HIVE CmiVolatileHive = NULL;
KSPIN_LOCK CmiKeyListLock;
LIST_ENTRY CmiHiveListHead;
KSPIN_LOCK CmiHiveListLock;
ERESOURCE CmiHiveListLock;
volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
volatile BOOLEAN CmiHiveSyncPending = FALSE;
@ -157,37 +157,37 @@ CmiCheckValues(BOOLEAN Verbose,
Index = 0;
while (TRUE)
{
BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
ValueInfo = ExAllocatePool(PagedPool, BufferSize);
BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
ValueInfo = ExAllocatePool(PagedPool, BufferSize);
Status = NtEnumerateValueKey(Key,
Index,
KeyNodeInformation,
ValueInfo,
BufferSize,
&ResultSize);
Status = NtEnumerateValueKey(Key,
Index,
KeyNodeInformation,
ValueInfo,
BufferSize,
&ResultSize);
if (!NT_SUCCESS(Status))
{
ExFreePool(ValueInfo);
if (Status == STATUS_NO_MORE_ENTRIES)
Status = STATUS_SUCCESS;
break;
}
{
ExFreePool(ValueInfo);
if (Status == STATUS_NO_MORE_ENTRIES)
Status = STATUS_SUCCESS;
break;
}
wcsncpy(Name,
ValueInfo->Name,
ValueInfo->NameLength / sizeof(WCHAR));
ValueInfo->Name,
ValueInfo->NameLength / sizeof(WCHAR));
if (Verbose)
{
DbgPrint("Value: %S\n", Name);
}
{
DbgPrint("Value: %S\n", Name);
}
/* FIXME: Check info. */
ExFreePool(ValueInfo);
Index++;
Index++;
}
assert(NT_SUCCESS(Status));
@ -264,7 +264,7 @@ CmInitializeRegistry(VOID)
PKEY_OBJECT NewKey;
HANDLE KeyHandle;
NTSTATUS Status;
/* Initialize the Key object type */
CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
assert(CmiKeyType);
@ -289,7 +289,7 @@ CmInitializeRegistry(VOID)
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
KeInitializeSpinLock(&CmiHiveListLock);
ExInitializeResourceLite(&CmiHiveListLock);
/* Build volatile registry store */
Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE);
@ -845,7 +845,7 @@ CmiInitHives(BOOLEAN SetUpBoot)
}
wcscat(ConfigPath, L"\\system32\\config");
DPRINT1("ConfigPath: %S\n", ConfigPath);
DPRINT("ConfigPath: %S\n", ConfigPath);
EndPtr = ConfigPath + wcslen(ConfigPath);
@ -944,14 +944,15 @@ CmShutdownRegistry(VOID)
{
PREGISTRY_HIVE Hive;
PLIST_ENTRY Entry;
// KIRQL oldlvl;
DPRINT1("CmShutdownRegistry() called\n");
/* Stop automatic hive synchronization */
CmiHiveSyncEnabled = FALSE;
// KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
Entry = CmiHiveListHead.Flink;
while (Entry != &CmiHiveListHead)
{
@ -976,27 +977,27 @@ CmShutdownRegistry(VOID)
Entry = Entry->Flink;
}
// KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
DPRINT1("CmShutdownRegistry() called\n");
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
DPRINT1("CmShutdownRegistry() done\n");
}
static VOID STDCALL
CmiHiveSyncDpcRoutine(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
VOID STDCALL
CmiHiveSyncRoutine(PVOID DeferredContext)
{
PREGISTRY_HIVE Hive;
PLIST_ENTRY Entry;
KIRQL oldlvl;
DPRINT1("CmiHiveSyncDpcRoutine() called\n");
DPRINT1("CmiHiveSyncRoutine() called\n");
CmiHiveSyncPending = FALSE;
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
Entry = CmiHiveListHead.Flink;
while (Entry != &CmiHiveListHead)
{
@ -1017,7 +1018,38 @@ CmiHiveSyncDpcRoutine(PKDPC Dpc,
Entry = Entry->Flink;
}
KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
DPRINT("DeferredContext %x\n", DeferredContext);
ExFreePool(DeferredContext);
}
static VOID STDCALL
CmiHiveSyncDpcRoutine(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
PWORK_QUEUE_ITEM WorkQueueItem;
WorkQueueItem = ExAllocatePool(NonPagedPool,
sizeof(WORK_QUEUE_ITEM));
if (WorkQueueItem == NULL)
{
DbgPrint("Failed to allocate work item\n");
return;
}
ExInitializeWorkItem(WorkQueueItem,
CmiHiveSyncRoutine,
WorkQueueItem);
DPRINT("DeferredContext %x\n", WorkQueueItem);
ExQueueWorkItem(WorkQueueItem,
CriticalWorkQueue);
}