Completed file cache support.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29442 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-03-08 15:56:07 +00:00
parent 224d5dc603
commit 4e5971527e
2 changed files with 142 additions and 17 deletions
@@ -10,6 +10,8 @@
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fs_cache.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
@@ -41,15 +43,26 @@ static const bigtime_t kUserlandServerlandPortTimeout = 10000000; // 10s
struct Volume::VNode : HashTableLink<VNode> { struct Volume::VNode : HashTableLink<VNode> {
ino_t id; ino_t id;
void* clientNode; void* clientNode;
void* fileCache;
int32 useCount; int32 useCount;
VNode(ino_t id, void* clientNode) VNode(ino_t id, void* clientNode)
: :
id(id), id(id),
clientNode(clientNode), clientNode(clientNode),
fileCache(NULL),
useCount(0) useCount(0)
{ {
} }
~VNode()
{
if (fileCache != NULL)
{
ERROR(("VNode %lld still has a file cache!\n", id));
file_cache_delete(fileCache);
}
}
}; };
@@ -295,8 +308,31 @@ PRINT(("get_vnode_removed(%ld, %lld, %p)\n", GetID(), vnid, removed));
status_t status_t
Volume::CreateFileCache(ino_t vnodeID, off_t size) Volume::CreateFileCache(ino_t vnodeID, off_t size)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node already have a file cache?
if (vnode->fileCache != NULL)
RETURN_ERROR(B_BAD_VALUE);
// create the file cache
locker.Unlock();
void* fileCache = file_cache_create(GetID(), vnodeID, size);
locker.Lock();
// re-check whether the node still lives
vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL) {
file_cache_delete(fileCache);
RETURN_ERROR(B_BAD_VALUE);
}
vnode->fileCache = fileCache;
return B_OK;
} }
@@ -304,8 +340,24 @@ Volume::CreateFileCache(ino_t vnodeID, off_t size)
status_t status_t
Volume::DeleteFileCache(ino_t vnodeID) Volume::DeleteFileCache(ino_t vnodeID)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node have a file cache
if (vnode->fileCache == NULL)
RETURN_ERROR(B_BAD_VALUE);
void* fileCache = vnode->fileCache;
vnode->fileCache = NULL;
locker.Unlock();
file_cache_delete(fileCache);
return B_OK;
} }
@@ -313,8 +365,29 @@ Volume::DeleteFileCache(ino_t vnodeID)
status_t status_t
Volume::SetFileCacheEnabled(ino_t vnodeID, bool enabled) Volume::SetFileCacheEnabled(ino_t vnodeID, bool enabled)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node have a file cache
if (vnode->fileCache == NULL)
RETURN_ERROR(B_BAD_VALUE);
void* fileCache = vnode->fileCache;
locker.Unlock();
// TODO: We should use some kind of ref counting to avoid that another thread
// deletes the file cache now that we have dropped the lock. Applies to the
// other file cache operations as well.
// enable/disable the file cache
if (enabled) {
file_cache_enable(fileCache);
return B_OK;
}
return file_cache_disable(fileCache);
} }
@@ -322,8 +395,21 @@ Volume::SetFileCacheEnabled(ino_t vnodeID, bool enabled)
status_t status_t
Volume::SetFileCacheSize(ino_t vnodeID, off_t size) Volume::SetFileCacheSize(ino_t vnodeID, off_t size)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node have a file cache
if (vnode->fileCache == NULL)
RETURN_ERROR(B_BAD_VALUE);
void* fileCache = vnode->fileCache;
locker.Unlock();
// set the size
return file_cache_set_size(fileCache, size);
} }
@@ -331,8 +417,21 @@ Volume::SetFileCacheSize(ino_t vnodeID, off_t size)
status_t status_t
Volume::SyncFileCache(ino_t vnodeID) Volume::SyncFileCache(ino_t vnodeID)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node have a file cache
if (vnode->fileCache == NULL)
RETURN_ERROR(B_BAD_VALUE);
void* fileCache = vnode->fileCache;
locker.Unlock();
// sync
return file_cache_sync(fileCache);
} }
@@ -341,18 +440,44 @@ status_t
Volume::ReadFileCache(ino_t vnodeID, void* cookie, Volume::ReadFileCache(ino_t vnodeID, void* cookie,
off_t offset, void* buffer, size_t* _size) off_t offset, void* buffer, size_t* _size)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node have a file cache
if (vnode->fileCache == NULL)
RETURN_ERROR(B_BAD_VALUE);
void* fileCache = vnode->fileCache;
locker.Unlock();
// read
return file_cache_read(fileCache, cookie, offset, buffer, _size);
} }
// WriteFileCache // WriteFileCache
status_t status_t
Volume::WriteFileCache(ino_t vnodeID, void* cookie, Volume::WriteFileCache(ino_t vnodeID, void* cookie,
off_t offset, const void *buffer, size_t *_size) off_t offset, const void* buffer, size_t* _size)
{ {
// TODO: Implement! // lookup the node
return B_NOT_SUPPORTED; MutexLocker locker(fLock);
VNode* vnode = fVNodes->Lookup(vnodeID);
if (vnode == NULL)
RETURN_ERROR(B_BAD_VALUE);
// does the node have a file cache
if (vnode->fileCache == NULL)
RETURN_ERROR(B_BAD_VALUE);
void* fileCache = vnode->fileCache;
locker.Unlock();
// read
return file_cache_write(fileCache, cookie, offset, buffer, _size);
} }
@@ -66,8 +66,8 @@ public:
status_t ReadFileCache(ino_t vnodeID, void* cookie, status_t ReadFileCache(ino_t vnodeID, void* cookie,
off_t offset, void* buffer, size_t* _size); off_t offset, void* buffer, size_t* _size);
status_t WriteFileCache(ino_t vnodeID, void* cookie, status_t WriteFileCache(ino_t vnodeID, void* cookie,
off_t offset, const void *buffer, off_t offset, const void* buffer,
size_t *_size); size_t* _size);
// FS // FS
status_t Mount(const char* device, uint32 flags, status_t Mount(const char* device, uint32 flags,