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.
This commit is contained in:
@@ -9,8 +9,6 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
|
||||||
static const int32 kEntriesPerGeneration = 1024;
|
|
||||||
|
|
||||||
static const int32 kEntryNotInArray = -1;
|
static const int32 kEntryNotInArray = -1;
|
||||||
static const int32 kEntryRemoved = -2;
|
static const int32 kEntryRemoved = -2;
|
||||||
|
|
||||||
@@ -33,14 +31,14 @@ EntryCacheGeneration::~EntryCacheGeneration()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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)
|
if (entries == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
memset(entries, 0, sizeof(EntryCacheEntry*) * kEntriesPerGeneration);
|
memset(entries, 0, sizeof(EntryCacheEntry*) * entries_size);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +65,7 @@ EntryCache::~EntryCache()
|
|||||||
free(entry);
|
free(entry);
|
||||||
entry = next;
|
entry = next;
|
||||||
}
|
}
|
||||||
|
delete[] fGenerations;
|
||||||
|
|
||||||
rw_lock_destroy(&fLock);
|
rw_lock_destroy(&fLock);
|
||||||
}
|
}
|
||||||
@@ -79,8 +78,12 @@ EntryCache::Init()
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
for (int32 i = 0; i < kGenerationCount; i++) {
|
fGenerationCount = 8;
|
||||||
error = fGenerations[i].Init();
|
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)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -96,6 +99,9 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID, bool missing)
|
|||||||
|
|
||||||
WriteLocker _(fLock);
|
WriteLocker _(fLock);
|
||||||
|
|
||||||
|
if (fGenerationCount == 0)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
EntryCacheEntry* entry = fEntries.Lookup(key);
|
EntryCacheEntry* entry = fEntries.Lookup(key);
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
entry->node_id = nodeID;
|
entry->node_id = nodeID;
|
||||||
@@ -168,8 +174,8 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID,
|
|||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int32 oldGeneration = atomic_get_and_set(&entry->generation,
|
const int32 oldGeneration = atomic_get_and_set(&entry->generation,
|
||||||
fCurrentGeneration);
|
fCurrentGeneration);
|
||||||
if (oldGeneration == fCurrentGeneration || entry->index < 0) {
|
if (oldGeneration == fCurrentGeneration || entry->index < 0) {
|
||||||
// The entry is already in the current generation or is being moved to
|
// The entry is already in the current generation or is being moved to
|
||||||
// it by another thread.
|
// it by another thread.
|
||||||
@@ -183,8 +189,8 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID,
|
|||||||
entry->index = kEntryNotInArray;
|
entry->index = kEntryNotInArray;
|
||||||
|
|
||||||
// add to the current generation
|
// add to the current generation
|
||||||
int32 index = atomic_add(&fGenerations[oldGeneration].next_index, 1);
|
const int32 index = atomic_add(&fGenerations[oldGeneration].next_index, 1);
|
||||||
if (index < kEntriesPerGeneration) {
|
if (index < fGenerations[fCurrentGeneration].entries_size) {
|
||||||
fGenerations[fCurrentGeneration].entries[index] = entry;
|
fGenerations[fCurrentGeneration].entries[index] = entry;
|
||||||
entry->index = index;
|
entry->index = index;
|
||||||
_nodeID = entry->node_id;
|
_nodeID = entry->node_id;
|
||||||
@@ -230,9 +236,11 @@ EntryCache::DebugReverseLookup(ino_t nodeID, ino_t& _dirID)
|
|||||||
void
|
void
|
||||||
EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry)
|
EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry)
|
||||||
{
|
{
|
||||||
|
ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
|
||||||
|
|
||||||
// the generation might not be full yet
|
// the generation might not be full yet
|
||||||
int32 index = fGenerations[fCurrentGeneration].next_index++;
|
int32 index = fGenerations[fCurrentGeneration].next_index++;
|
||||||
if (index < kEntriesPerGeneration) {
|
if (index < fGenerations[fCurrentGeneration].entries_size) {
|
||||||
fGenerations[fCurrentGeneration].entries[index] = entry;
|
fGenerations[fCurrentGeneration].entries[index] = entry;
|
||||||
entry->generation = fCurrentGeneration;
|
entry->generation = fCurrentGeneration;
|
||||||
entry->index = index;
|
entry->index = index;
|
||||||
@@ -240,8 +248,8 @@ EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we have to clear the oldest generation
|
// we have to clear the oldest generation
|
||||||
int32 newGeneration = (fCurrentGeneration + 1) % kGenerationCount;
|
const int32 newGeneration = (fCurrentGeneration + 1) % fGenerationCount;
|
||||||
for (int32 i = 0; i < kEntriesPerGeneration; i++) {
|
for (int32 i = 0; i < fGenerations[newGeneration].entries_size; i++) {
|
||||||
EntryCacheEntry* otherEntry = fGenerations[newGeneration].entries[i];
|
EntryCacheEntry* otherEntry = fGenerations[newGeneration].entries[i];
|
||||||
if (otherEntry == NULL)
|
if (otherEntry == NULL)
|
||||||
continue;
|
continue;
|
||||||
@@ -253,8 +261,8 @@ EntryCache::_AddEntryToCurrentGeneration(EntryCacheEntry* entry)
|
|||||||
|
|
||||||
// set the new generation and add the entry
|
// set the new generation and add the entry
|
||||||
fCurrentGeneration = newGeneration;
|
fCurrentGeneration = newGeneration;
|
||||||
fGenerations[newGeneration].next_index = 1;
|
|
||||||
fGenerations[newGeneration].entries[0] = entry;
|
fGenerations[newGeneration].entries[0] = entry;
|
||||||
|
fGenerations[newGeneration].next_index = 1;
|
||||||
entry->generation = newGeneration;
|
entry->generation = newGeneration;
|
||||||
entry->index = 0;
|
entry->index = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,13 @@ struct EntryCacheEntry {
|
|||||||
|
|
||||||
struct EntryCacheGeneration {
|
struct EntryCacheGeneration {
|
||||||
int32 next_index;
|
int32 next_index;
|
||||||
|
int32 entries_size;
|
||||||
EntryCacheEntry** entries;
|
EntryCacheEntry** entries;
|
||||||
|
|
||||||
EntryCacheGeneration();
|
EntryCacheGeneration();
|
||||||
~EntryCacheGeneration();
|
~EntryCacheGeneration();
|
||||||
|
|
||||||
status_t Init();
|
status_t Init(int32 entriesSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -99,8 +100,6 @@ public:
|
|||||||
const char* DebugReverseLookup(ino_t nodeID, ino_t& _dirID);
|
const char* DebugReverseLookup(ino_t nodeID, ino_t& _dirID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int32 kGenerationCount = 8;
|
|
||||||
|
|
||||||
typedef BOpenHashTable<EntryCacheHashDefinition> EntryTable;
|
typedef BOpenHashTable<EntryCacheHashDefinition> EntryTable;
|
||||||
typedef DoublyLinkedList<EntryCacheEntry> EntryList;
|
typedef DoublyLinkedList<EntryCacheEntry> EntryList;
|
||||||
|
|
||||||
@@ -111,7 +110,8 @@ private:
|
|||||||
private:
|
private:
|
||||||
rw_lock fLock;
|
rw_lock fLock;
|
||||||
EntryTable fEntries;
|
EntryTable fEntries;
|
||||||
EntryCacheGeneration fGenerations[kGenerationCount];
|
int32 fGenerationCount;
|
||||||
|
EntryCacheGeneration* fGenerations;
|
||||||
int32 fCurrentGeneration;
|
int32 fCurrentGeneration;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user