nfs4: Fix some cache revalidator problems

This commit is contained in:
Pawel Dziepak
2012-09-14 19:00:30 +02:00
parent e422d059c8
commit cae470f922
7 changed files with 47 additions and 33 deletions
@@ -86,8 +86,12 @@ CacheRevalidator::_DirectoryCacheRevalidator()
continue; continue;
} }
if (current->Lock() != B_OK) current->Lock();
if (!current->Valid()) {
RemoveDirectory(current);
current->Unlock();
continue; continue;
}
if (current->ExpireTime() > system_time()) { if (current->ExpireTime() > system_time()) {
current->Unlock(); current->Unlock();
@@ -110,7 +114,6 @@ CacheRevalidator::_DirectoryCacheRevalidator()
if (current->Revalidate() == B_OK) if (current->Revalidate() == B_OK)
AddDirectory(current); AddDirectory(current);
locker.Unlock();
current->Unlock(); current->Unlock();
} }
} }
@@ -58,8 +58,10 @@ CacheRevalidator::Unlock()
inline void inline void
CacheRevalidator::AddDirectory(DirectoryCache* cache) CacheRevalidator::AddDirectory(DirectoryCache* cache)
{ {
cache->fRevalidated = true; if (!cache->fRevalidated) {
fDirectoryCaches.InsertAfter(fDirectoryCaches.Tail(), cache); cache->fRevalidated = true;
fDirectoryCaches.InsertAfter(fDirectoryCaches.Tail(), cache);
}
} }
@@ -70,9 +70,8 @@ DirectoryCache::~DirectoryCache()
void void
DirectoryCache::ResetAndLock() DirectoryCache::Reset()
{ {
mutex_lock(&fLock);
Trash(); Trash();
fExpireTime = system_time() + kExpirationTime; fExpireTime = system_time() + kExpirationTime;
fTrashed = false; fTrashed = false;
@@ -40,11 +40,12 @@ public:
DirectoryCache(Inode* inode, bool attr = false); DirectoryCache(Inode* inode, bool attr = false);
~DirectoryCache(); ~DirectoryCache();
inline status_t Lock(); inline void Lock();
inline void Unlock(); inline void Unlock();
void ResetAndLock(); void Reset();
void Trash(); void Trash();
inline bool Valid();
status_t AddEntry(const char* name, ino_t node, status_t AddEntry(const char* name, ino_t node,
bool created = false); bool created = false);
@@ -87,18 +88,13 @@ private:
}; };
inline status_t inline void
DirectoryCache::Lock() DirectoryCache::Lock()
{ {
mutex_lock(&fLock); mutex_lock(&fLock);
if (fTrashed) {
mutex_unlock(&fLock);
return B_ERROR;
}
return B_OK;
} }
inline void inline void
DirectoryCache::Unlock() DirectoryCache::Unlock()
{ {
@@ -106,6 +102,13 @@ DirectoryCache::Unlock()
} }
inline bool
DirectoryCache::Valid()
{
return !fTrashed;
}
inline DirectoryCacheSnapshot* inline DirectoryCacheSnapshot*
DirectoryCache::GetSnapshot() DirectoryCache::GetSnapshot()
{ {
+18 -12
View File
@@ -197,8 +197,9 @@ Inode::LookUp(const char* name, ino_t* id)
return result; return result;
fFileSystem->Revalidator().Lock(); fFileSystem->Revalidator().Lock();
if (fCache->Lock() != B_OK) { fCache->Lock();
fCache->ResetAndLock(); if (!fCache->Valid()) {
fCache->Reset();
fCache->SetChangeInfo(change); fCache->SetChangeInfo(change);
} else { } else {
fFileSystem->Revalidator().RemoveDirectory(fCache); fFileSystem->Revalidator().RemoveDirectory(fCache);
@@ -232,15 +233,16 @@ Inode::Link(Inode* dir, const char* name)
fFileSystem->InoIdMap()->AddEntry(fi, fInfo.fFileId); fFileSystem->InoIdMap()->AddEntry(fi, fInfo.fFileId);
if (dir->fCache->Lock() == B_OK) { dir->fCache->Lock();
if (dir->fCache->Valid()) {
if (changeInfo.fAtomic if (changeInfo.fAtomic
&& dir->fCache->ChangeInfo() == changeInfo.fBefore) { && dir->fCache->ChangeInfo() == changeInfo.fBefore) {
dir->fCache->AddEntry(name, fInfo.fFileId, true); dir->fCache->AddEntry(name, fInfo.fFileId, true);
dir->fCache->SetChangeInfo(changeInfo.fAfter); dir->fCache->SetChangeInfo(changeInfo.fAfter);
} else if (dir->fCache->ChangeInfo() != changeInfo.fBefore) } else if (dir->fCache->ChangeInfo() != changeInfo.fBefore)
dir->fCache->Trash(); dir->fCache->Trash();
dir->fCache->Unlock();
} }
dir->fCache->Unlock();
notify_entry_created(fFileSystem->DevId(), dir->ID(), name, ID()); notify_entry_created(fFileSystem->DevId(), dir->ID(), name, ID());
@@ -270,15 +272,16 @@ Inode::Remove(const char* name, FileType type, ino_t* id)
return result; return result;
DirectoryCache* cache = type != NF4NAMEDATTR ? fCache : fAttrCache; DirectoryCache* cache = type != NF4NAMEDATTR ? fCache : fAttrCache;
if (cache->Lock() == B_OK) { cache->Lock();
if (cache->Valid()) {
if (changeInfo.fAtomic if (changeInfo.fAtomic
&& fCache->ChangeInfo() == changeInfo.fBefore) { && fCache->ChangeInfo() == changeInfo.fBefore) {
cache->RemoveEntry(name); cache->RemoveEntry(name);
cache->SetChangeInfo(changeInfo.fAfter); cache->SetChangeInfo(changeInfo.fAfter);
} else if (cache->ChangeInfo() != changeInfo.fBefore) } else if (cache->ChangeInfo() != changeInfo.fBefore)
cache->Trash(); cache->Trash();
cache->Unlock();
} }
cache->Unlock();
fFileSystem->Root()->MakeInfoInvalid(); fFileSystem->Root()->MakeInfoInvalid();
if (id != NULL) if (id != NULL)
@@ -333,29 +336,31 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName,
from->fFileSystem->Root()->MakeInfoInvalid(); from->fFileSystem->Root()->MakeInfoInvalid();
DirectoryCache* cache = attribute ? from->fAttrCache : from->fCache; DirectoryCache* cache = attribute ? from->fAttrCache : from->fCache;
if (cache->Lock() == B_OK) { cache->Lock();
if (cache->Valid()) {
if (fromChange.fAtomic if (fromChange.fAtomic
&& cache->ChangeInfo() == fromChange.fBefore) { && cache->ChangeInfo() == fromChange.fBefore) {
cache->RemoveEntry(fromName); cache->RemoveEntry(fromName);
cache->SetChangeInfo(fromChange.fAfter); cache->SetChangeInfo(fromChange.fAfter);
} else if (cache->ChangeInfo() != fromChange.fBefore) } else if (cache->ChangeInfo() != fromChange.fBefore)
cache->Trash(); cache->Trash();
cache->Unlock();
} }
cache->Unlock();
if (id != NULL) if (id != NULL)
*id = FileIdToInoT(fileID); *id = FileIdToInoT(fileID);
cache = attribute ? to->fAttrCache : to->fCache; cache = attribute ? to->fAttrCache : to->fCache;
if (cache->Lock() == B_OK) { cache->Lock();
if (cache->Valid()) {
if (toChange.fAtomic if (toChange.fAtomic
&& cache->ChangeInfo() == toChange.fBefore) { && cache->ChangeInfo() == toChange.fBefore) {
cache->AddEntry(toName, fileID, true); cache->AddEntry(toName, fileID, true);
cache->SetChangeInfo(toChange.fAfter); cache->SetChangeInfo(toChange.fAfter);
} else if (to->fCache->ChangeInfo() != toChange.fBefore) } else if (to->fCache->ChangeInfo() != toChange.fBefore)
cache->Trash(); cache->Trash();
cache->Unlock();
} }
cache->Unlock();
if (attribute) { if (attribute) {
notify_attribute_changed(from->fFileSystem->DevId(), from->ID(), notify_attribute_changed(from->fFileSystem->DevId(), from->ID(),
@@ -396,14 +401,15 @@ Inode::CreateObject(const char* name, const char* path, int mode, FileType type)
if (result != B_OK) if (result != B_OK)
return B_OK; return B_OK;
if (fCache->Lock() == B_OK) { fCache->Lock();
if (fCache->Valid()) {
if (changeInfo.fAtomic && fCache->ChangeInfo() == changeInfo.fBefore) { if (changeInfo.fAtomic && fCache->ChangeInfo() == changeInfo.fBefore) {
fCache->AddEntry(name, fileID, true); fCache->AddEntry(name, fileID, true);
fCache->SetChangeInfo(changeInfo.fAfter); fCache->SetChangeInfo(changeInfo.fAfter);
} else if (fCache->ChangeInfo() != changeInfo.fBefore) } else if (fCache->ChangeInfo() != changeInfo.fBefore)
fCache->Trash(); fCache->Trash();
fCache->Unlock();
} }
fCache->Unlock();
notify_entry_created(fFileSystem->DevId(), ID(), name, notify_entry_created(fFileSystem->DevId(), ID(), name,
FileIdToInoT(fileID)); FileIdToInoT(fileID));
@@ -302,11 +302,11 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
DirectoryCache* cache = cookie->fAttrDir ? fAttrCache : fCache; DirectoryCache* cache = cookie->fAttrDir ? fAttrCache : fCache;
if (cookie->fSnapshot == NULL) { if (cookie->fSnapshot == NULL) {
fFileSystem->Revalidator().Lock(); fFileSystem->Revalidator().Lock();
if (cache->Lock() != B_OK) { cache->Lock();
cache->ResetAndLock(); if (!cache->Valid())
} else { cache->Reset();
else
fFileSystem->Revalidator().RemoveDirectory(cache); fFileSystem->Revalidator().RemoveDirectory(cache);
}
cookie->fSnapshot = cache->GetSnapshot(); cookie->fSnapshot = cache->GetSnapshot();
if (cookie->fSnapshot == NULL) { if (cookie->fSnapshot == NULL) {
@@ -42,15 +42,16 @@ Inode::CreateState(const char* name, int mode, int perms, OpenState* state,
fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID)); fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID));
if (fCache->Lock() == B_OK) { fCache->Lock();
if (fCache->Valid()) {
if (changeInfo.fAtomic if (changeInfo.fAtomic
&& fCache->ChangeInfo() == changeInfo.fBefore) { && fCache->ChangeInfo() == changeInfo.fBefore) {
fCache->AddEntry(name, fileID, true); fCache->AddEntry(name, fileID, true);
fCache->SetChangeInfo(changeInfo.fAfter); fCache->SetChangeInfo(changeInfo.fAfter);
} else if (fCache->ChangeInfo() != changeInfo.fBefore) } else if (fCache->ChangeInfo() != changeInfo.fBefore)
fCache->Trash(); fCache->Trash();
fCache->Unlock();
} }
fCache->Unlock();
state->fFileSystem = fFileSystem; state->fFileSystem = fFileSystem;
state->fInfo = fi; state->fInfo = fi;