From 25866ebeeb754fb0e55f5f80d157746f9b28f0dc Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 3 Aug 2022 17:43:12 -0400 Subject: [PATCH] kernel/fs: Refactor EntryCache to not use constant array sizes. Instead set them in the Init functions. For now, the same hard-coded sizes are used, so aside from slightly increased storage on two classes (or not even due to padding), this has no functional change. --- src/system/kernel/fs/EntryCache.cpp | 40 +++++++++++++++++------------ src/system/kernel/fs/EntryCache.h | 8 +++--- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/system/kernel/fs/EntryCache.cpp b/src/system/kernel/fs/EntryCache.cpp index 63743b8f4c..cb8973e6a3 100644 --- a/src/system/kernel/fs/EntryCache.cpp +++ b/src/system/kernel/fs/EntryCache.cpp @@ -9,8 +9,6 @@ #include -static const int32 kEntriesPerGeneration = 1024; - static const int32 kEntryNotInArray = -1; static const int32 kEntryRemoved = -2; @@ -33,14 +31,14 @@ EntryCacheGeneration::~EntryCacheGeneration() status_t -EntryCacheGeneration::Init() +EntryCacheGeneration::Init(int32 entriesSize) { - entries = new(std::nothrow) EntryCacheEntry*[kEntriesPerGeneration]; + entries_size = entriesSize; + entries = new(std::nothrow) EntryCacheEntry*[entries_size]; if (entries == NULL) return B_NO_MEMORY; - memset(entries, 0, sizeof(EntryCacheEntry*) * kEntriesPerGeneration); - + memset(entries, 0, sizeof(EntryCacheEntry*) * entries_size); return B_OK; } @@ -67,6 +65,7 @@ EntryCache::~EntryCache() free(entry); entry = next; } + delete[] fGenerations; rw_lock_destroy(&fLock); } @@ -79,8 +78,12 @@ EntryCache::Init() if (error != B_OK) return error; - for (int32 i = 0; i < kGenerationCount; i++) { - error = fGenerations[i].Init(); + fGenerationCount = 8; + int32 entriesSize = 1024; + + fGenerations = new(std::nothrow) EntryCacheGeneration[fGenerationCount]; + for (int32 i = 0; i < fGenerationCount; i++) { + error = fGenerations[i].Init(entriesSize); if (error != B_OK) return error; } @@ -96,6 +99,9 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID, bool missing) WriteLocker _(fLock); + if (fGenerationCount == 0) + return B_NO_MEMORY; + EntryCacheEntry* entry = fEntries.Lookup(key); if (entry != NULL) { entry->node_id = nodeID; @@ -168,8 +174,8 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID, if (entry == NULL) return false; - int32 oldGeneration = atomic_get_and_set(&entry->generation, - fCurrentGeneration); + const int32 oldGeneration = atomic_get_and_set(&entry->generation, + fCurrentGeneration); if (oldGeneration == fCurrentGeneration || entry->index < 0) { // The entry is already in the current generation or is being moved to // it by another thread. @@ -183,8 +189,8 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID, entry->index = kEntryNotInArray; // add to the current generation - int32 index = atomic_add(&fGenerations[oldGeneration].next_index, 1); - if (index < kEntriesPerGeneration) { + const int32 index = atomic_add(&fGenerations[oldGeneration].next_index, 1); + if (index < fGenerations[fCurrentGeneration].entries_size) { fGenerations[fCurrentGeneration].entries[index] = entry; entry->index = index; _nodeID = entry->node_id; @@ -230,9 +236,11 @@ EntryCache::DebugReverseLookup(ino_t nodeID, ino_t& _dirID) void EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry) { + ASSERT_WRITE_LOCKED_RW_LOCK(&fLock); + // the generation might not be full yet int32 index = fGenerations[fCurrentGeneration].next_index++; - if (index < kEntriesPerGeneration) { + if (index < fGenerations[fCurrentGeneration].entries_size) { fGenerations[fCurrentGeneration].entries[index] = entry; entry->generation = fCurrentGeneration; entry->index = index; @@ -240,8 +248,8 @@ EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry) } // we have to clear the oldest generation - int32 newGeneration = (fCurrentGeneration + 1) % kGenerationCount; - for (int32 i = 0; i < kEntriesPerGeneration; i++) { + const int32 newGeneration = (fCurrentGeneration + 1) % fGenerationCount; + for (int32 i = 0; i < fGenerations[newGeneration].entries_size; i++) { EntryCacheEntry* otherEntry = fGenerations[newGeneration].entries[i]; if (otherEntry == NULL) continue; @@ -253,8 +261,8 @@ EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry) // set the new generation and add the entry fCurrentGeneration = newGeneration; - fGenerations[newGeneration].next_index = 1; fGenerations[newGeneration].entries[0] = entry; + fGenerations[newGeneration].next_index = 1; entry->generation = newGeneration; entry->index = 0; } diff --git a/src/system/kernel/fs/EntryCache.h b/src/system/kernel/fs/EntryCache.h index 4e0a950c4d..5c58305b59 100644 --- a/src/system/kernel/fs/EntryCache.h +++ b/src/system/kernel/fs/EntryCache.h @@ -44,12 +44,13 @@ struct EntryCacheEntry { struct EntryCacheGeneration { int32 next_index; + int32 entries_size; EntryCacheEntry** entries; EntryCacheGeneration(); ~EntryCacheGeneration(); - status_t Init(); + status_t Init(int32 entriesSize); }; @@ -99,8 +100,6 @@ public: const char* DebugReverseLookup(ino_t nodeID, ino_t& _dirID); private: - static const int32 kGenerationCount = 8; - typedef BOpenHashTable EntryTable; typedef DoublyLinkedList EntryList; @@ -111,7 +110,8 @@ private: private: rw_lock fLock; EntryTable fEntries; - EntryCacheGeneration fGenerations[kGenerationCount]; + int32 fGenerationCount; + EntryCacheGeneration* fGenerations; int32 fCurrentGeneration; };