nfs4: Remove CacheRevalidator

There is no point in periodically revalidating all existing directory caches.
Directory snapshot can be revalidated when readdir is invoked.
This commit is contained in:
Pawel Dziepak
2013-01-04 20:05:15 +01:00
parent 332621d196
commit 4d12040737
10 changed files with 61 additions and 287 deletions
@@ -1,122 +0,0 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, [email protected]
*/
#include "CacheRevalidator.h"
#include <fs_cache.h>
#include "NFS4Defs.h"
CacheRevalidator::CacheRevalidator()
:
fThreadCancel(false),
fWaitCancel(create_sem(0, NULL))
{
mutex_init(&fDirectoryCachesLock, NULL);
_StartRevalidator();
}
CacheRevalidator::~CacheRevalidator()
{
fThreadCancel = true;
release_sem(fWaitCancel);
status_t result;
wait_for_thread(fThread, &result);
delete_sem(fThreadCancel);
mutex_destroy(&fDirectoryCachesLock);
}
status_t
CacheRevalidator::_StartRevalidator()
{
fThreadCancel = false;
fThread = spawn_kernel_thread(&CacheRevalidator::_DirectoryRevalidatorStart,
"NFSv4 Cache Revalidator", B_NORMAL_PRIORITY, this);
if (fThread < B_OK)
return fThread;
status_t result = resume_thread(fThread);
if (result != B_OK) {
kill_thread(fThread);
return result;
}
return B_OK;
}
status_t
CacheRevalidator::_DirectoryRevalidatorStart(void* object)
{
ASSERT(object != NULL);
CacheRevalidator* revalidator = reinterpret_cast<CacheRevalidator*>(object);
revalidator->_DirectoryCacheRevalidator();
return B_OK;
}
void
CacheRevalidator::_DirectoryCacheRevalidator()
{
while (!fThreadCancel) {
MutexLocker locker(fDirectoryCachesLock);
DirectoryCache* current = fDirectoryCaches.Head();
if (current == NULL) {
locker.Unlock();
status_t result = acquire_sem_etc(fWaitCancel, 1,
B_RELATIVE_TIMEOUT, DirectoryCache::kExpirationTime);
if (result != B_TIMED_OUT) {
if (result == B_OK)
release_sem(fWaitCancel);
return;
}
continue;
}
current->Lock();
if (!current->Valid()) {
RemoveDirectory(current);
current->Unlock();
continue;
}
if (current->ExpireTime() > system_time()) {
current->Unlock();
locker.Unlock();
status_t result = acquire_sem_etc(fWaitCancel, 1,
B_ABSOLUTE_TIMEOUT, current->ExpireTime());
if (result != B_TIMED_OUT) {
if (result == B_OK)
release_sem(fWaitCancel);
return;
}
continue;
}
fDirectoryCaches.RemoveHead();
current->fRevalidated = false;
if (current->Revalidate() == B_OK)
AddDirectory(current);
current->Unlock();
}
}
@@ -1,83 +0,0 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, [email protected]
*/
#ifndef CACHEREVALIDATOR_H
#define CACHEREVALIDATOR_H
#include <lock.h>
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>
#include "DirectoryCache.h"
class CacheRevalidator {
public:
CacheRevalidator();
~CacheRevalidator();
inline void Lock();
inline void Unlock();
inline void AddDirectory(DirectoryCache* cache);
inline void RemoveDirectory(DirectoryCache* cache);
private:
void _DirectoryCacheRevalidator();
static status_t _DirectoryRevalidatorStart(void* object);
status_t _StartRevalidator();
thread_id fThread;
bool fThreadCancel;
sem_id fWaitCancel;
DoublyLinkedList<DirectoryCache> fDirectoryCaches;
mutex fDirectoryCachesLock;
};
inline void
CacheRevalidator::Lock()
{
mutex_lock(&fDirectoryCachesLock);
}
inline void
CacheRevalidator::Unlock()
{
mutex_unlock(&fDirectoryCachesLock);
}
inline void
CacheRevalidator::AddDirectory(DirectoryCache* cache)
{
ASSERT(cache != NULL);
if (!cache->fRevalidated) {
cache->fRevalidated = true;
fDirectoryCaches.InsertAfter(fDirectoryCaches.Tail(), cache);
}
}
inline void
CacheRevalidator::RemoveDirectory(DirectoryCache* cache)
{
ASSERT(cache != NULL);
if (cache->fRevalidated == true)
fDirectoryCaches.Remove(cache);
cache->fRevalidated = false;
}
#endif // CACHEREVALIDATOR_H
@@ -11,6 +11,7 @@
#include <SupportDefs.h>
#include "DirectoryCache.h"
#include "FileSystem.h"
@@ -92,10 +92,6 @@ DirectoryCache::DirectoryCache(Inode* inode, bool attr)
DirectoryCache::~DirectoryCache()
{
fInode->GetFileSystem()->Revalidator().Lock();
fInode->GetFileSystem()->Revalidator().RemoveDirectory(this);
fInode->GetFileSystem()->Revalidator().Unlock();
mutex_destroy(&fLock);
}
@@ -119,7 +115,7 @@ DirectoryCache::Trash()
delete current;
}
SetSnapshot(NULL);
_SetSnapshot(NULL);
fTrashed = true;
}
@@ -207,7 +203,7 @@ DirectoryCache::RemoveEntry(const char* name)
void
DirectoryCache::SetSnapshot(DirectoryCacheSnapshot* snapshot)
DirectoryCache::_SetSnapshot(DirectoryCacheSnapshot* snapshot)
{
if (fDirectoryCache != NULL)
fDirectoryCache->ReleaseReference();
@@ -215,9 +211,48 @@ DirectoryCache::SetSnapshot(DirectoryCacheSnapshot* snapshot)
}
status_t
DirectoryCache::_LoadSnapshot(bool trash)
{
DirectoryCacheSnapshot* oldSnapshot = fDirectoryCache;
if (oldSnapshot != NULL)
oldSnapshot->AcquireReference();
if (trash)
Trash();
DirectoryCacheSnapshot* newSnapshot;
status_t result = fInode->GetDirSnapshot(&newSnapshot, NULL, &fChange,
fAttrDir);
if (result != B_OK) {
if (oldSnapshot != NULL)
oldSnapshot->ReleaseReference();
return result;
}
newSnapshot->AcquireReference();
_SetSnapshot(newSnapshot);
fExpireTime = system_time() + kExpirationTime;
fTrashed = false;
if (oldSnapshot != NULL)
NotifyChanges(oldSnapshot, newSnapshot);
if (oldSnapshot != NULL)
oldSnapshot->ReleaseReference();
newSnapshot->ReleaseReference();
return B_OK;
}
status_t
DirectoryCache::Revalidate()
{
if (fExpireTime < system_time())
return B_OK;
uint64 change;
if (fInode->GetChangeInfo(&change, fAttrDir) != B_OK) {
Trash();
@@ -229,34 +264,7 @@ DirectoryCache::Revalidate()
return B_OK;
}
DirectoryCacheSnapshot* oldSnapshot = fDirectoryCache;
if (oldSnapshot == NULL) {
Trash();
return B_ERROR;
}
oldSnapshot->AcquireReference();
Trash();
DirectoryCacheSnapshot* newSnapshot;
status_t result = fInode->GetDirSnapshot(&newSnapshot, NULL, &fChange,
fAttrDir);
if (result != B_OK) {
oldSnapshot->ReleaseReference();
return B_ERROR;
}
newSnapshot->AcquireReference();
SetSnapshot(newSnapshot);
fExpireTime = system_time() + kExpirationTime;
fTrashed = false;
NotifyChanges(oldSnapshot, newSnapshot);
oldSnapshot->ReleaseReference();
newSnapshot->ReleaseReference();
return B_OK;
return _LoadSnapshot(true);
}
@@ -38,7 +38,7 @@ struct DirectoryCacheSnapshot : public KernelReferenceable {
~DirectoryCacheSnapshot();
};
class DirectoryCache : public DoublyLinkedListLinkImpl<DirectoryCache> {
class DirectoryCache {
public:
DirectoryCache(Inode* inode, bool attr = false);
~DirectoryCache();
@@ -54,7 +54,6 @@ public:
bool created = false);
void RemoveEntry(const char* name);
void SetSnapshot(DirectoryCacheSnapshot* snapshot);
inline DirectoryCacheSnapshot* GetSnapshot();
inline SinglyLinkedList<NameCacheEntry>& EntriesList();
@@ -66,7 +65,6 @@ public:
inline uint64 ChangeInfo();
inline Inode* GetInode();
inline time_t ExpireTime();
static const bigtime_t kExpirationTime = 15000000;
@@ -76,6 +74,9 @@ protected:
DirectoryCacheSnapshot* newSnapshot);
private:
void _SetSnapshot(DirectoryCacheSnapshot* snapshot);
status_t _LoadSnapshot(bool trash);
SinglyLinkedList<NameCacheEntry> fNameCache;
DirectoryCacheSnapshot* fDirectoryCache;
@@ -115,6 +116,8 @@ DirectoryCache::Valid()
inline DirectoryCacheSnapshot*
DirectoryCache::GetSnapshot()
{
if (fDirectoryCache == NULL)
_LoadSnapshot(false);
return fDirectoryCache;
}
@@ -164,12 +167,5 @@ DirectoryCache::GetInode()
}
inline time_t
DirectoryCache::ExpireTime()
{
return fExpireTime;
}
#endif // DIRECTORYCACHE_H
@@ -9,7 +9,6 @@
#define FILESYSTEM_H
#include "CacheRevalidator.h"
#include "Delegation.h"
#include "InodeIdMap.h"
#include "NFS4Defs.h"
@@ -51,8 +50,6 @@ public:
void RemoveDelegation(Delegation* delegation);
Delegation* GetDelegation(const FileHandle& handle);
inline CacheRevalidator& Revalidator();
inline bool IsAttrSupported(Attribute attr) const;
inline uint32 ExpireType() const;
@@ -79,8 +76,6 @@ public:
private:
FileSystem(const MountConfiguration& config);
CacheRevalidator fCacheRevalidator;
mutex fDelegationLock;
DoublyLinkedList<Delegation> fDelegationList;
AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation;
@@ -113,13 +108,6 @@ private:
};
inline CacheRevalidator&
FileSystem::Revalidator()
{
return fCacheRevalidator;
}
inline RootInode*
FileSystem::Root()
{
@@ -204,20 +204,15 @@ Inode::LookUp(const char* name, ino_t* id)
if (result != B_OK)
return result;
fFileSystem->Revalidator().Lock();
fCache->Lock();
if (!fCache->Valid()) {
fCache->Reset();
fCache->SetChangeInfo(change);
} else {
fFileSystem->Revalidator().RemoveDirectory(fCache);
} else
fCache->ValidateChangeInfo(change);
}
fCache->AddEntry(name, *id);
fFileSystem->Revalidator().AddDirectory(fCache);
fCache->Unlock();
fFileSystem->Revalidator().Unlock();
return B_OK;
}
@@ -9,6 +9,7 @@
#define INODE_H
#include "DirectoryCache.h"
#include "MetadataCache.h"
#include "NFS4Inode.h"
#include "OpenState.h"
@@ -317,30 +317,21 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
status_t result;
DirectoryCache* cache = cookie->fAttrDir ? fAttrCache : fCache;
if (cookie->fSnapshot == NULL) {
fFileSystem->Revalidator().Lock();
cache->Lock();
if (!cache->Valid())
cache->Reset();
else
fFileSystem->Revalidator().RemoveDirectory(cache);
result = cache->Revalidate();
if (result != B_OK) {
cache->Unlock();
return result;
}
DirectoryCacheSnapshot* snapshot = cache->GetSnapshot();
if (snapshot == NULL) {
uint64 change;
result = GetDirSnapshot(&snapshot, cookie, &change,
cookie->fAttrDir);
if (result != B_OK) {
cache->Unlock();
fFileSystem->Revalidator().Unlock();
return result;
}
cache->ValidateChangeInfo(change);
cache->SetSnapshot(snapshot);
}
ASSERT(snapshot != NULL);
cookie->fSnapshot = new DirectoryCacheSnapshot(*snapshot);
fFileSystem->Revalidator().AddDirectory(cache);
cache->Unlock();
fFileSystem->Revalidator().Unlock();
if (cookie->fSnapshot == NULL)
return B_NO_MEMORY;
}
char* buffer = reinterpret_cast<char*>(_buffer);
@@ -4,7 +4,6 @@ UsePrivateKernelHeaders ;
UsePrivateHeaders shared ;
KernelAddon nfs4 :
CacheRevalidator.cpp
Cookie.cpp
Connection.cpp
Delegation.cpp