EntryCache: Add entry_cache_add_missing() for negative caching.
It provides a way for filesystems to cache a lookup failure and therefore prevents repeated lookups of missing entries. This is a common scenario for example in command lookup and compiling, where each directory in PATH or each include directory is searched for the given entry.
This commit is contained in:
@@ -104,6 +104,8 @@ extern status_t file_map_translate(void *map, off_t offset, size_t size,
|
||||
/* entry cache */
|
||||
extern status_t entry_cache_add(dev_t mountID, ino_t dirID, const char* name,
|
||||
ino_t nodeID);
|
||||
extern status_t entry_cache_add_missing(dev_t mountID, ino_t dirID,
|
||||
const char* name);
|
||||
extern status_t entry_cache_remove(dev_t mountID, ino_t dirID,
|
||||
const char* name);
|
||||
|
||||
|
||||
@@ -871,6 +871,7 @@
|
||||
|
||||
/* entry cache */
|
||||
#define entry_cache_add fssh_entry_cache_add
|
||||
#define entry_cache_add_missing fssh_entry_cache_add_missing
|
||||
#define entry_cache_remove fssh_entry_cache_remove
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -126,6 +126,8 @@ extern fssh_status_t fssh_file_map_translate(void *_map, fssh_off_t offset,
|
||||
extern fssh_status_t fssh_entry_cache_add(fssh_dev_t mountID,
|
||||
fssh_ino_t dirID, const char* name,
|
||||
fssh_ino_t nodeID);
|
||||
extern fssh_status_t fssh_entry_cache_add_missing(fssh_dev_t mountID,
|
||||
fssh_ino_t dirID, const char* name);
|
||||
extern fssh_status_t fssh_entry_cache_remove(fssh_dev_t mountID,
|
||||
fssh_ino_t dirID, const char* name);
|
||||
|
||||
|
||||
@@ -17,6 +17,13 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
entry_cache_remove(dev_t mountID, ino_t dirID, const char* name)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ EntryCache::Init()
|
||||
|
||||
|
||||
status_t
|
||||
EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID)
|
||||
EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID, bool missing)
|
||||
{
|
||||
EntryCacheKey key(dirID, name);
|
||||
|
||||
@@ -99,6 +99,7 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID)
|
||||
EntryCacheEntry* entry = fEntries.Lookup(key);
|
||||
if (entry != NULL) {
|
||||
entry->node_id = nodeID;
|
||||
entry->missing = missing;
|
||||
if (entry->generation != fCurrentGeneration) {
|
||||
if (entry->index >= 0) {
|
||||
fGenerations[entry->generation].entries[entry->index] = NULL;
|
||||
@@ -114,6 +115,7 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID)
|
||||
|
||||
entry->node_id = nodeID;
|
||||
entry->dir_id = dirID;
|
||||
entry->missing = missing;
|
||||
entry->generation = fCurrentGeneration;
|
||||
entry->index = kEntryNotInArray;
|
||||
strcpy(entry->name, name);
|
||||
@@ -155,7 +157,8 @@ EntryCache::Remove(ino_t dirID, const char* name)
|
||||
|
||||
|
||||
bool
|
||||
EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID)
|
||||
EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID,
|
||||
bool& _missing)
|
||||
{
|
||||
EntryCacheKey key(dirID, name);
|
||||
|
||||
@@ -171,6 +174,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID)
|
||||
// The entry is already in the current generation or is being moved to
|
||||
// it by another thread.
|
||||
_nodeID = entry->node_id;
|
||||
_missing = entry->missing;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -184,6 +188,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID)
|
||||
fGenerations[fCurrentGeneration].entries[index] = entry;
|
||||
entry->index = index;
|
||||
_nodeID = entry->node_id;
|
||||
_missing = entry->missing;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -201,6 +206,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID)
|
||||
_AddEntryToCurrentGeneration(entry);
|
||||
|
||||
_nodeID = entry->node_id;
|
||||
_missing = entry->missing;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ struct EntryCacheEntry {
|
||||
ino_t dir_id;
|
||||
int32 generation;
|
||||
int32 index;
|
||||
bool missing;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
@@ -87,12 +88,12 @@ public:
|
||||
status_t Init();
|
||||
|
||||
status_t Add(ino_t dirID, const char* name,
|
||||
ino_t nodeID);
|
||||
ino_t nodeID, bool missing);
|
||||
|
||||
status_t Remove(ino_t dirID, const char* name);
|
||||
|
||||
bool Lookup(ino_t dirID, const char* name,
|
||||
ino_t& nodeID);
|
||||
ino_t& nodeID, bool& missing);
|
||||
|
||||
const char* DebugReverseLookup(ino_t nodeID, ino_t& _dirID);
|
||||
|
||||
|
||||
@@ -2089,9 +2089,12 @@ static status_t
|
||||
lookup_dir_entry(struct vnode* dir, const char* name, struct vnode** _vnode)
|
||||
{
|
||||
ino_t id;
|
||||
bool missing;
|
||||
|
||||
if (dir->mount->entry_cache.Lookup(dir->id, name, id))
|
||||
return get_vnode(dir->device, id, _vnode, true, false);
|
||||
if (dir->mount->entry_cache.Lookup(dir->id, name, id, missing)) {
|
||||
return missing ? B_ENTRY_NOT_FOUND
|
||||
: get_vnode(dir->device, id, _vnode, true, false);
|
||||
}
|
||||
|
||||
status_t status = FS_CALL(dir, lookup, name, &id);
|
||||
if (status != B_OK)
|
||||
@@ -4011,7 +4014,22 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID)
|
||||
return B_BAD_VALUE;
|
||||
locker.Unlock();
|
||||
|
||||
return mount->entry_cache.Add(dirID, name, nodeID);
|
||||
return mount->entry_cache.Add(dirID, name, nodeID, false);
|
||||
}
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name)
|
||||
{
|
||||
// lookup mount -- the caller is required to make sure that the mount
|
||||
// won't go away
|
||||
MutexLocker locker(sMountMutex);
|
||||
struct fs_mount* mount = find_mount(mountID);
|
||||
if (mount == NULL)
|
||||
return B_BAD_VALUE;
|
||||
locker.Unlock();
|
||||
|
||||
return mount->entry_cache.Add(dirID, name, -1, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2277,6 +2277,15 @@ fssh_entry_cache_add(fssh_dev_t mountID, fssh_ino_t dirID, const char* name,
|
||||
}
|
||||
|
||||
|
||||
extern "C" fssh_status_t
|
||||
fssh_entry_cache_add_missing(fssh_dev_t mountID, fssh_ino_t dirID,
|
||||
const char* name)
|
||||
{
|
||||
// We don't implement an entry cache in the FS shell.
|
||||
return FSSH_B_OK;
|
||||
}
|
||||
|
||||
|
||||
extern "C" fssh_status_t
|
||||
fssh_entry_cache_remove(fssh_dev_t mountID, fssh_ino_t dirID, const char* name)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user