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:
Michael Lotz
2015-08-20 21:25:56 +02:00
parent 883b3e1d5c
commit efb0a3a853
8 changed files with 53 additions and 7 deletions
+2
View File
@@ -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
////////////////////////////////////////////////////////////////////////////////
+2
View File
@@ -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)
{
+8 -2
View File
@@ -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;
}
+3 -2
View File
@@ -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);
+21 -3
View File
@@ -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);
}
+9
View File
@@ -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)
{