Author: fireball
Date: Sun Dec 16 18:41:48 2007
New Revision: 31280
URL:
http://svn.reactos.org/svn/reactos?rev=31280&view=rev
Log:
- Add shared->Exclusive promotion support to value cache routines as well.
- Implement CmpCompareNewValueDataAgainstKCBCache as an optimization during Set Value Key
operations, so that if the value is already identical, it will not be written again.
Modified:
trunk/reactos/ntoskrnl/config/cmapi.c
trunk/reactos/ntoskrnl/config/cmvalche.c
Modified: trunk/reactos/ntoskrnl/config/cmapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmapi.c (original)
+++ trunk/reactos/ntoskrnl/config/cmapi.c Sun Dec 16 18:41:48 2007
@@ -296,7 +296,11 @@
}
/* Search for the value */
- SearchResult = SearchFail;
+ SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb,
+ ValueName,
+ Type,
+ Data,
+ DataLength);
if (SearchResult == SearchNeedExclusiveLock)
{
/* Try again with the exclusive lock */
Modified: trunk/reactos/ntoskrnl/config/cmvalche.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmvalche.c…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmvalche.c (original)
+++ trunk/reactos/ntoskrnl/config/cmvalche.c Sun Dec 16 18:41:48 2007
@@ -55,12 +55,10 @@
*ValueListToRelease = HCELL_NIL;
*IndexIsCached = FALSE;
- /* Get the hive */
+ /* Get the hive and value ceche */
Hive = Kcb->KeyHive;
+ ChildList = &Kcb->ValueCache;
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
-
- /* Get the child value cache */
- //ChildList = &Kcb->ValueCache;
ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;
/* Check if the value is cached */
@@ -73,10 +71,20 @@
}
else
{
+ /* Make sure the KCB is locked exclusive */
+ if (!(CmpIsKcbLockedExclusive(Kcb)) &&
+ !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
+ {
+ /* We need the exclusive lock */
+ return SearchNeedExclusiveLock;
+ }
+
/* Select the value list as our cell, and get the actual list array */
CellToRelease = ChildList->ValueList;
*CellData = (PCELL_DATA)HvGetCell(Hive, CellToRelease);
if (!(*CellData)) return SearchFail;
+
+ /* FIXME: Here we would cache the value */
/* Return the cell to be released */
*ValueListToRelease = CellToRelease;
@@ -210,12 +218,10 @@
*CellToRelease = HCELL_NIL;
*Value = NULL;
- /* Get the hive */
+ /* Get the hive and child list */
Hive = Kcb->KeyHive;
+ ChildList = &Kcb->ValueCache;
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
-
- /* Get the child value cache */
- //ChildList = &Kcb->ValueCache;
ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;
/* Check if the child list has any entries */
@@ -226,7 +232,13 @@
&CellData,
&IndexIsCached,
&Cell);
- if (SearchResult != SearchSuccess) return SearchResult;
+ if (SearchResult != SearchSuccess)
+ {
+ /* We either failed or need the exclusive lock */
+ ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
+ ASSERT(Cell == HCELL_NIL);
+ return SearchResult;
+ }
/* The index shouldn't be cached right now */
if (IndexIsCached) ASSERT_VALUE_CACHE();
@@ -251,7 +263,13 @@
IndexIsCached,
ValueIsCached,
CellToRelease);
- if (SearchResult != SearchSuccess) return SearchResult;
+ if (SearchResult != SearchSuccess)
+ {
+ /* We either failed or need the exclusive lock */
+ ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
+ ASSERT(Cell == HCELL_NIL);
+ return SearchResult;
+ }
/* Check if the both the index and the value are cached */
if ((IndexIsCached) && (*ValueIsCached))
@@ -647,3 +665,143 @@
/* Return the search result as well */
return Result;
}
+
+VALUE_SEARCH_RETURN_TYPE
+NTAPI
+CmpCompareNewValueDataAgainstKCBCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize)
+{
+ VALUE_SEARCH_RETURN_TYPE SearchResult;
+ PCM_KEY_NODE KeyNode;
+ PCM_CACHED_VALUE *CachedValue;
+ ULONG Index;
+ PCM_KEY_VALUE Value;
+ BOOLEAN ValueCached, BufferAllocated = FALSE;
+ PVOID Buffer;
+ HCELL_INDEX ValueCellToRelease = HCELL_NIL, CellToRelease = HCELL_NIL;
+ BOOLEAN IsSmall;
+ ULONG CompareResult;
+ PAGED_CODE();
+
+ /* Check if this is a symlink */
+ if (Kcb->Flags & KEY_SYM_LINK)
+ {
+ /* We need the exclusive lock */
+ if (!(CmpIsKcbLockedExclusive(Kcb)) &&
+ !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
+ {
+ /* We need the exclusive lock */
+ return SearchNeedExclusiveLock;
+ }
+
+ /* Otherwise, get the key node */
+ KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
+ if (!KeyNode) return SearchFail;
+
+ /* Cleanup the KCB cache */
+ CmpCleanUpKcbValueCache(Kcb);
+
+ /* Sanity checks */
+ ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
+ ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
+
+ /* Set the value cache */
+ Kcb->ValueCache.Count = KeyNode->ValueList.Count;
+ Kcb->ValueCache.ValueList = KeyNode->ValueList.List;
+
+ /* Release the cell */
+ HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
+ }
+
+ /* Do the search */
+ SearchResult = CmpFindValueByNameFromCache(Kcb,
+ ValueName,
+ &CachedValue,
+ &Index,
+ &Value,
+ &ValueCached,
+ &ValueCellToRelease);
+ if (SearchResult == SearchNeedExclusiveLock)
+ {
+ /* We need the exclusive lock */
+ ASSERT(!CmpIsKcbLockedExclusive(Kcb));
+ ASSERT(ValueCellToRelease == HCELL_NIL);
+ ASSERT(Value == NULL);
+ goto Quickie;
+ }
+ else if (SearchResult == SearchSuccess)
+ {
+ /* Sanity check */
+ ASSERT(Value);
+
+ /* First of all, check if the key size and type matches */
+ if ((Type == Value->Type) &&
+ (DataSize == (Value->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE)))
+ {
+ /* Check if this is a small key */
+ IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
+ if (IsSmall)
+ {
+ /* Compare against the data directly */
+ Buffer = &Value->Data;
+ }
+ else
+ {
+ /* Do a search */
+ SearchResult = CmpGetValueDataFromCache(Kcb,
+ CachedValue,
+ (PCELL_DATA)Value,
+ ValueCached,
+ &Buffer,
+ &BufferAllocated,
+ &CellToRelease);
+ if (SearchResult != SearchSuccess)
+ {
+ /* Sanity checks */
+ ASSERT(Buffer == NULL);
+ ASSERT(BufferAllocated == FALSE);
+ goto Quickie;
+ }
+ }
+
+ /* Now check the data size */
+ if (DataSize)
+ {
+ /* Do the compare */
+ CompareResult = RtlCompareMemory(Buffer,
+ Data,
+ DataSize &
+ ~CM_KEY_VALUE_SPECIAL_SIZE);
+ }
+ else
+ {
+ /* It's equal */
+ CompareResult = 0;
+ }
+
+ /* Now check if the compare wasn't equal */
+ if (CompareResult != DataSize) SearchResult = SearchFail;
+ }
+ else
+ {
+ /* The length or type isn't equal */
+ SearchResult = SearchFail;
+ }
+ }
+
+Quickie:
+ /* Release the value cell */
+ if (ValueCellToRelease) HvReleaseCell(Kcb->KeyHive, ValueCellToRelease);
+
+ /* Free the buffer */
+ if (BufferAllocated) ExFreePool(Buffer);
+
+ /* Free the cell */
+ if (CellToRelease) HvReleaseCell(Kcb->KeyHive, CellToRelease);
+
+ /* Return the search result */
+ return SearchResult;
+}