From f42efbcd26947b3394c94f7462ae2c0f6455a1d3 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 1 Jan 2010 20:51:30 +0000 Subject: [PATCH] Moved the entry cache implementation into its own file. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34843 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/fs/EntryCache.h | 171 ++++++++++++++++++++++++++++++ src/system/kernel/fs/vfs.cpp | 155 +-------------------------- 2 files changed, 172 insertions(+), 154 deletions(-) create mode 100644 src/system/kernel/fs/EntryCache.h diff --git a/src/system/kernel/fs/EntryCache.h b/src/system/kernel/fs/EntryCache.h new file mode 100644 index 0000000000..0af38eceaa --- /dev/null +++ b/src/system/kernel/fs/EntryCache.h @@ -0,0 +1,171 @@ +/* + * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef ENTRY_CACHE_H +#define ENTRY_CACHE_H + + +#include + +#include +#include +#include +#include + + +const static uint32 kMaxEntryCacheEntryCount = 8192; + // Maximum number of entries per entry cache. It's a hard limit ATM. + +struct EntryCacheKey { + EntryCacheKey(ino_t dirID, const char* name) + : + dir_id(dirID), + name(name) + { + } + + ino_t dir_id; + const char* name; +}; + + +struct EntryCacheEntry : DoublyLinkedListLinkImpl { + EntryCacheEntry* hash_link; + ino_t node_id; + ino_t dir_id; + char name[1]; +}; + + +struct EntryCacheHashDefinition { + typedef EntryCacheKey KeyType; + typedef EntryCacheEntry ValueType; + + uint32 HashKey(const EntryCacheKey& key) const + { + return (uint32)key.dir_id ^ (uint32)(key.dir_id >> 32) + ^ hash_hash_string(key.name); + } + + size_t Hash(const EntryCacheEntry* value) const + { + return (uint32)value->dir_id ^ (uint32)(value->dir_id >> 32) + ^ hash_hash_string(value->name); + } + + bool Compare(const EntryCacheKey& key, const EntryCacheEntry* value) const + { + return value->dir_id == key.dir_id + && strcmp(value->name, key.name) == 0; + } + + EntryCacheEntry*& GetLink(EntryCacheEntry* value) const + { + return value->hash_link; + } +}; + + +class EntryCache { +public: + EntryCache() + { + mutex_init(&fLock, "entry cache"); + + new(&fEntries) EntryTable; + new(&fUsedEntries) EntryList; + fEntryCount = 0; + } + + ~EntryCache() + { + while (EntryCacheEntry* entry = fUsedEntries.Head()) + _Remove(entry); + + mutex_destroy(&fLock); + } + + status_t Init() + { + return fEntries.Init(); + } + + status_t Add(ino_t dirID, const char* name, ino_t nodeID) + { + MutexLocker _(fLock); + + EntryCacheEntry* entry = fEntries.Lookup(EntryCacheKey(dirID, name)); + if (entry != NULL) { + entry->node_id = nodeID; + return B_OK; + } + + if (fEntryCount >= kMaxEntryCacheEntryCount) + _Remove(fUsedEntries.Head()); + + entry = (EntryCacheEntry*)malloc(sizeof(EntryCacheEntry) + + strlen(name)); + if (entry == NULL) + return B_NO_MEMORY; + + entry->node_id = nodeID; + entry->dir_id = dirID; + strcpy(entry->name, name); + + fEntries.Insert(entry); + fUsedEntries.Add(entry); + fEntryCount++; + + return B_OK; + } + + status_t Remove(ino_t dirID, const char* name) + { + MutexLocker _(fLock); + + EntryCacheEntry* entry = fEntries.Lookup(EntryCacheKey(dirID, name)); + if (entry == NULL) + return B_ENTRY_NOT_FOUND; + + _Remove(entry); + + return B_OK; + } + + bool Lookup(ino_t dirID, const char* name, ino_t& nodeID) + { + MutexLocker _(fLock); + + EntryCacheEntry* entry = fEntries.Lookup(EntryCacheKey(dirID, name)); + if (entry == NULL) + return false; + + // requeue at the end + fUsedEntries.Remove(entry); + fUsedEntries.Add(entry); + + nodeID = entry->node_id; + return true; + } + + void _Remove(EntryCacheEntry* entry) + { + fEntries.Remove(entry); + fUsedEntries.Remove(entry); + free(entry); + fEntryCount--; + } + +private: + typedef BOpenHashTable EntryTable; + typedef DoublyLinkedList EntryList; + + mutex fLock; + EntryTable fEntries; + EntryList fUsedEntries; // LRU queue (LRU entry at the head) + uint32 fEntryCount; +}; + + +#endif // ENTRY_CACHE_H diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 1ebcd57a1c..270978084d 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -49,11 +49,11 @@ #include #include #include -#include #include #include #include +#include "EntryCache.h" #include "fifo.h" #include "IORequest.h" #include "../cache/vnode_store.h" @@ -110,163 +110,10 @@ const static uint32 kMaxUnusedVnodes = 8192; // It may be chosen with respect to the available memory or enhanced // by some timestamp/frequency heurism. -const static uint32 kMaxEntryCacheEntryCount = 8192; - // Maximum number of entries per entry cache. It's a hard limit ATM. - const static size_t kMaxPathLength = 65536; // The absolute maximum path length (for getcwd() - this is not depending // on PATH_MAX -struct EntryCacheKey { - EntryCacheKey(ino_t dirID, const char* name) - : - dir_id(dirID), - name(name) - { - } - - ino_t dir_id; - const char* name; -}; - - -struct EntryCacheEntry : DoublyLinkedListLinkImpl { - EntryCacheEntry* hash_link; - ino_t node_id; - ino_t dir_id; - char name[1]; -}; - - -struct EntryCacheHashDefinition { - typedef EntryCacheKey KeyType; - typedef EntryCacheEntry ValueType; - - uint32 HashKey(const EntryCacheKey& key) const - { - return (uint32)key.dir_id ^ (uint32)(key.dir_id >> 32) - ^ hash_hash_string(key.name); - } - - size_t Hash(const EntryCacheEntry* value) const - { - return (uint32)value->dir_id ^ (uint32)(value->dir_id >> 32) - ^ hash_hash_string(value->name); - } - - bool Compare(const EntryCacheKey& key, const EntryCacheEntry* value) const - { - return value->dir_id == key.dir_id - && strcmp(value->name, key.name) == 0; - } - - EntryCacheEntry*& GetLink(EntryCacheEntry* value) const - { - return value->hash_link; - } -}; - - -class EntryCache { -public: - EntryCache() - { - mutex_init(&fLock, "entry cache"); - - new(&fEntries) EntryTable; - new(&fUsedEntries) EntryList; - fEntryCount = 0; - } - - ~EntryCache() - { - while (EntryCacheEntry* entry = fUsedEntries.Head()) - _Remove(entry); - - mutex_destroy(&fLock); - } - - status_t Init() - { - return fEntries.Init(); - } - - status_t Add(ino_t dirID, const char* name, ino_t nodeID) - { - MutexLocker _(fLock); - - EntryCacheEntry* entry = fEntries.Lookup(EntryCacheKey(dirID, name)); - if (entry != NULL) { - entry->node_id = nodeID; - return B_OK; - } - - if (fEntryCount >= kMaxEntryCacheEntryCount) - _Remove(fUsedEntries.Head()); - - entry = (EntryCacheEntry*)malloc(sizeof(EntryCacheEntry) - + strlen(name)); - if (entry == NULL) - return B_NO_MEMORY; - - entry->node_id = nodeID; - entry->dir_id = dirID; - strcpy(entry->name, name); - - fEntries.Insert(entry); - fUsedEntries.Add(entry); - fEntryCount++; - - return B_OK; - } - - status_t Remove(ino_t dirID, const char* name) - { - MutexLocker _(fLock); - - EntryCacheEntry* entry = fEntries.Lookup(EntryCacheKey(dirID, name)); - if (entry == NULL) - return B_ENTRY_NOT_FOUND; - - _Remove(entry); - - return B_OK; - } - - bool Lookup(ino_t dirID, const char* name, ino_t& nodeID) - { - MutexLocker _(fLock); - - EntryCacheEntry* entry = fEntries.Lookup(EntryCacheKey(dirID, name)); - if (entry == NULL) - return false; - - // requeue at the end - fUsedEntries.Remove(entry); - fUsedEntries.Add(entry); - - nodeID = entry->node_id; - return true; - } - - void _Remove(EntryCacheEntry* entry) - { - fEntries.Remove(entry); - fUsedEntries.Remove(entry); - free(entry); - fEntryCount--; - } - -private: - typedef BOpenHashTable EntryTable; - typedef DoublyLinkedList EntryList; - - mutex fLock; - EntryTable fEntries; - EntryList fUsedEntries; // LRU queue (LRU entry at the head) - uint32 fEntryCount; -}; - struct vnode : fs_vnode, DoublyLinkedListLinkImpl { struct vnode* next;