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 KSPIN_LOCK CmiKeyListLock;
extern LIST_ENTRY CmiHiveListHead; extern LIST_ENTRY CmiHiveListHead;
extern KSPIN_LOCK CmiHiveListLock; extern ERESOURCE CmiHiveListLock;
VOID VOID

View file

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

View file

@ -809,7 +809,6 @@ CmiCreateRegistryHive(PWSTR Filename,
BOOLEAN CreateNew) BOOLEAN CreateNew)
{ {
PREGISTRY_HIVE Hive; PREGISTRY_HIVE Hive;
KIRQL oldlvl;
NTSTATUS Status; NTSTATUS Status;
DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename); DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename);
@ -851,10 +850,14 @@ CmiCreateRegistryHive(PWSTR Filename,
ExInitializeResourceLite(&Hive->HiveResource); ExInitializeResourceLite(&Hive->HiveResource);
/* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
/* Add the new hive to the hive list */ /* Add the new hive to the hive list */
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
InsertHeadList(&CmiHiveListHead, &Hive->HiveList); InsertHeadList(&CmiHiveListHead, &Hive->HiveList);
KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
VERIFY_REGISTRY_HIVE(Hive); VERIFY_REGISTRY_HIVE(Hive);
@ -869,12 +872,14 @@ CmiCreateRegistryHive(PWSTR Filename,
NTSTATUS NTSTATUS
CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive) CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
{ {
KIRQL oldlvl; /* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
/* Remove hive from hive list */ /* Remove hive from hive list */
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
RemoveEntryList(&RegistryHive->HiveList); RemoveEntryList(&RegistryHive->HiveList);
KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
/* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
/* FIXME: Remove attached keys and values */ /* FIXME: Remove attached keys and values */
@ -1385,46 +1390,56 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
DPRINT1("CmiRemoveSubKey() called\n"); DPRINT1("CmiRemoveSubKey() called\n");
/* Remove the key from the parent key's hash block */ /* Remove the key from the parent key's hash block */
HashBlock = CmiGetBlock(RegistryHive, if (ParentKey->KeyCell->HashTableOffset != -1)
ParentKey->KeyCell->HashTableOffset,
NULL);
if (HashBlock != NULL)
{ {
CmiRemoveKeyFromHashTable(RegistryHive, DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey->KeyCell->HashTableOffset)
HashBlock, HashBlock = CmiGetBlock(RegistryHive,
SubKey->BlockOffset); ParentKey->KeyCell->HashTableOffset,
CmiMarkBlockDirty(RegistryHive, NULL);
ParentKey->KeyCell->HashTableOffset); 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 */ /* Remove the key's hash block */
DPRINT1("HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset) if (SubKey->KeyCell->HashTableOffset != -1)
if (SubKey->KeyCell->HashTableOffset != 0)
{ {
DPRINT1("SubKey HashTableOffset %lx\n", SubKey->KeyCell->HashTableOffset)
HashBlock = CmiGetBlock(RegistryHive, HashBlock = CmiGetBlock(RegistryHive,
SubKey->KeyCell->HashTableOffset, SubKey->KeyCell->HashTableOffset,
NULL); NULL);
DPRINT1("HashBlock %p\n", HashBlock) DPRINT1("SubKey HashBlock %p\n", HashBlock)
if (HashBlock != NULL) if (HashBlock != NULL)
{ {
CmiDestroyBlock(RegistryHive, CmiDestroyBlock(RegistryHive,
HashBlock, HashBlock,
SubKey->KeyCell->HashTableOffset); SubKey->KeyCell->HashTableOffset);
SubKey->KeyCell->HashTableOffset = -1;
} }
SubKey->KeyCell->HashTableOffset = 0;
} }
CHECKPOINT1; /* Decrement the number of the parent key's sub keys */
/* Remove the key from the parent key's hash block */ if (ParentKey != NULL)
ParentKey->KeyCell->NumberOfSubKeys--; {
CmiMarkBlockDirty(RegistryHive, DPRINT1("ParentKey %p\n", ParentKey)
ParentKey->BlockOffset); ParentKey->KeyCell->NumberOfSubKeys--;
NtQuerySystemTime((PTIME)&ParentKey->KeyCell->LastWriteTime);
CmiMarkBlockDirty(RegistryHive,
ParentKey->BlockOffset);
}
CHECKPOINT1;
/* Destroy key cell */ /* Destroy key cell */
CmiDestroyBlock(RegistryHive, CmiDestroyBlock(RegistryHive,
SubKey->KeyCell, SubKey->KeyCell,
SubKey->BlockOffset); SubKey->BlockOffset);
SubKey->BlockOffset = -1;
SubKey->KeyCell = NULL;
return(STATUS_SUCCESS); 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -35,7 +35,7 @@ PREGISTRY_HIVE CmiVolatileHive = NULL;
KSPIN_LOCK CmiKeyListLock; KSPIN_LOCK CmiKeyListLock;
LIST_ENTRY CmiHiveListHead; LIST_ENTRY CmiHiveListHead;
KSPIN_LOCK CmiHiveListLock; ERESOURCE CmiHiveListLock;
volatile BOOLEAN CmiHiveSyncEnabled = FALSE; volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
volatile BOOLEAN CmiHiveSyncPending = FALSE; volatile BOOLEAN CmiHiveSyncPending = FALSE;
@ -157,37 +157,37 @@ CmiCheckValues(BOOLEAN Verbose,
Index = 0; Index = 0;
while (TRUE) while (TRUE)
{ {
BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
ValueInfo = ExAllocatePool(PagedPool, BufferSize); ValueInfo = ExAllocatePool(PagedPool, BufferSize);
Status = NtEnumerateValueKey(Key, Status = NtEnumerateValueKey(Key,
Index, Index,
KeyNodeInformation, KeyNodeInformation,
ValueInfo, ValueInfo,
BufferSize, BufferSize,
&ResultSize); &ResultSize);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ExFreePool(ValueInfo); ExFreePool(ValueInfo);
if (Status == STATUS_NO_MORE_ENTRIES) if (Status == STATUS_NO_MORE_ENTRIES)
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
break; break;
} }
wcsncpy(Name, wcsncpy(Name,
ValueInfo->Name, ValueInfo->Name,
ValueInfo->NameLength / sizeof(WCHAR)); ValueInfo->NameLength / sizeof(WCHAR));
if (Verbose) if (Verbose)
{ {
DbgPrint("Value: %S\n", Name); DbgPrint("Value: %S\n", Name);
} }
/* FIXME: Check info. */ /* FIXME: Check info. */
ExFreePool(ValueInfo); ExFreePool(ValueInfo);
Index++; Index++;
} }
assert(NT_SUCCESS(Status)); assert(NT_SUCCESS(Status));
@ -264,7 +264,7 @@ CmInitializeRegistry(VOID)
PKEY_OBJECT NewKey; PKEY_OBJECT NewKey;
HANDLE KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; NTSTATUS Status;
/* Initialize the Key object type */ /* Initialize the Key object type */
CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
assert(CmiKeyType); assert(CmiKeyType);
@ -289,7 +289,7 @@ CmInitializeRegistry(VOID)
/* Initialize the hive list */ /* Initialize the hive list */
InitializeListHead(&CmiHiveListHead); InitializeListHead(&CmiHiveListHead);
KeInitializeSpinLock(&CmiHiveListLock); ExInitializeResourceLite(&CmiHiveListLock);
/* Build volatile registry store */ /* Build volatile registry store */
Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE); Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE);
@ -845,7 +845,7 @@ CmiInitHives(BOOLEAN SetUpBoot)
} }
wcscat(ConfigPath, L"\\system32\\config"); wcscat(ConfigPath, L"\\system32\\config");
DPRINT1("ConfigPath: %S\n", ConfigPath); DPRINT("ConfigPath: %S\n", ConfigPath);
EndPtr = ConfigPath + wcslen(ConfigPath); EndPtr = ConfigPath + wcslen(ConfigPath);
@ -944,14 +944,15 @@ CmShutdownRegistry(VOID)
{ {
PREGISTRY_HIVE Hive; PREGISTRY_HIVE Hive;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
// KIRQL oldlvl;
DPRINT1("CmShutdownRegistry() called\n"); DPRINT1("CmShutdownRegistry() called\n");
/* Stop automatic hive synchronization */ /* Stop automatic hive synchronization */
CmiHiveSyncEnabled = FALSE; CmiHiveSyncEnabled = FALSE;
// KeAcquireSpinLock(&CmiHiveListLock,&oldlvl); /* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
Entry = CmiHiveListHead.Flink; Entry = CmiHiveListHead.Flink;
while (Entry != &CmiHiveListHead) while (Entry != &CmiHiveListHead)
{ {
@ -976,27 +977,27 @@ CmShutdownRegistry(VOID)
Entry = Entry->Flink; Entry = Entry->Flink;
} }
// KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
DPRINT1("CmShutdownRegistry() called\n"); /* Release hive list lock */
ExReleaseResourceLite(&CmiHiveListLock);
DPRINT1("CmShutdownRegistry() done\n");
} }
static VOID STDCALL VOID STDCALL
CmiHiveSyncDpcRoutine(PKDPC Dpc, CmiHiveSyncRoutine(PVOID DeferredContext)
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{ {
PREGISTRY_HIVE Hive; PREGISTRY_HIVE Hive;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
KIRQL oldlvl;
DPRINT1("CmiHiveSyncDpcRoutine() called\n"); DPRINT1("CmiHiveSyncRoutine() called\n");
CmiHiveSyncPending = FALSE; CmiHiveSyncPending = FALSE;
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl); /* Acquire hive list lock exclusively */
ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
Entry = CmiHiveListHead.Flink; Entry = CmiHiveListHead.Flink;
while (Entry != &CmiHiveListHead) while (Entry != &CmiHiveListHead)
{ {
@ -1017,7 +1018,38 @@ CmiHiveSyncDpcRoutine(PKDPC Dpc,
Entry = Entry->Flink; 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);
} }