nfs4: Add directory and name basic implementation
This commit is contained in:
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
release_sem(fWaitCancel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->Lock();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
release_sem(fWaitCancel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fDirectoryCaches.RemoveHead();
|
||||||
|
|
||||||
|
if (current->Revalidate() == B_OK)
|
||||||
|
AddDirectory(current);
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
current->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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/DoublyLinkedQueue.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;
|
||||||
|
|
||||||
|
DoublyLinkedQueue<DirectoryCache> fDirectoryCaches;
|
||||||
|
mutex fDirectoryCachesLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
CacheRevalidator::Lock()
|
||||||
|
{
|
||||||
|
mutex_lock(&fDirectoryCachesLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
CacheRevalidator::Unlock()
|
||||||
|
{
|
||||||
|
mutex_unlock(&fDirectoryCachesLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
CacheRevalidator::AddDirectory(DirectoryCache* cache)
|
||||||
|
{
|
||||||
|
fDirectoryCaches.Add(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
CacheRevalidator::RemoveDirectory(DirectoryCache* cache)
|
||||||
|
{
|
||||||
|
fDirectoryCaches.Remove(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CACHEREVALIDATOR_H
|
||||||
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "DirectoryCache.h"
|
||||||
|
|
||||||
|
#include <fs_cache.h>
|
||||||
|
|
||||||
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
|
DirectoryCache::DirectoryCache(Inode* inode)
|
||||||
|
:
|
||||||
|
fInode(inode),
|
||||||
|
fTrashed(true)
|
||||||
|
{
|
||||||
|
mutex_init(&fLock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DirectoryCache::~DirectoryCache()
|
||||||
|
{
|
||||||
|
mutex_destroy(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DirectoryCache::ResetAndLock()
|
||||||
|
{
|
||||||
|
mutex_lock(&fLock);
|
||||||
|
Trash();
|
||||||
|
fExpireTime = system_time() + kExpirationTime;
|
||||||
|
fTrashed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DirectoryCache::Trash()
|
||||||
|
{
|
||||||
|
while (!fNameCache.IsEmpty()) {
|
||||||
|
NameCacheEntry* current = fNameCache.RemoveHead();
|
||||||
|
entry_cache_remove(fInode->GetFileSystem()->DevId(), fInode->ID(),
|
||||||
|
current->fName);
|
||||||
|
free(const_cast<char*>(current->fName));
|
||||||
|
delete current;
|
||||||
|
}
|
||||||
|
|
||||||
|
fTrashed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DirectoryCache::AddEntry(const char* name, ino_t node)
|
||||||
|
{
|
||||||
|
NameCacheEntry* entry = new(std::nothrow) NameCacheEntry;
|
||||||
|
if (entry == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
entry->fName = strdup(name);
|
||||||
|
if (entry->fName == NULL) {
|
||||||
|
delete entry;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
entry->fNode = node;
|
||||||
|
fNameCache.Add(entry);
|
||||||
|
|
||||||
|
return entry_cache_add(fInode->GetFileSystem()->DevId(), fInode->ID(), name,
|
||||||
|
node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DirectoryCache::RemoveEntry(const char* name)
|
||||||
|
{
|
||||||
|
SinglyLinkedList<NameCacheEntry>::Iterator iterator
|
||||||
|
= fNameCache.GetIterator();
|
||||||
|
NameCacheEntry* previous = NULL;
|
||||||
|
NameCacheEntry* current = iterator.Next();
|
||||||
|
while (current != NULL) {
|
||||||
|
if (strcmp(current->fName, name) == 0) {
|
||||||
|
free(const_cast<char*>(current->fName));
|
||||||
|
delete current;
|
||||||
|
|
||||||
|
fNameCache.Remove(previous, current);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
current = iterator.Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_cache_remove(fInode->GetFileSystem()->DevId(), fInode->ID(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DirectoryCache::Revalidate()
|
||||||
|
{
|
||||||
|
uint64 change;
|
||||||
|
if (fInode->GetChangeInfo(&change) == B_OK && change == fChange) {
|
||||||
|
fExpireTime = system_time() + kExpirationTime;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trash();
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef DIRECTORYCACHE_H
|
||||||
|
#define DIRECTORYCACHE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/SinglyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Inode;
|
||||||
|
|
||||||
|
struct NameCacheEntry :
|
||||||
|
public SinglyLinkedListLinkImpl<NameCacheEntry> {
|
||||||
|
ino_t fNode;
|
||||||
|
const char* fName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DirectoryCache : public DoublyLinkedListLinkImpl<DirectoryCache> {
|
||||||
|
public:
|
||||||
|
DirectoryCache(Inode* inode);
|
||||||
|
~DirectoryCache();
|
||||||
|
|
||||||
|
inline status_t Lock();
|
||||||
|
inline void Unlock();
|
||||||
|
|
||||||
|
void ResetAndLock();
|
||||||
|
void Trash();
|
||||||
|
|
||||||
|
status_t AddEntry(const char* name, ino_t node);
|
||||||
|
void RemoveEntry(const char* name);
|
||||||
|
|
||||||
|
inline SinglyLinkedList<NameCacheEntry>& EntriesList();
|
||||||
|
|
||||||
|
status_t Revalidate();
|
||||||
|
|
||||||
|
inline status_t ValidateChangeInfo(uint64 change);
|
||||||
|
inline void SetChangeInfo(uint64 change);
|
||||||
|
inline uint64 ChangeInfo();
|
||||||
|
|
||||||
|
inline Inode* GetInode();
|
||||||
|
inline time_t ExpireTime();
|
||||||
|
|
||||||
|
static const bigtime_t kExpirationTime = 5000000;
|
||||||
|
private:
|
||||||
|
SinglyLinkedList<NameCacheEntry> fNameCache;
|
||||||
|
|
||||||
|
Inode* fInode;
|
||||||
|
|
||||||
|
bool fTrashed;
|
||||||
|
mutex fLock;
|
||||||
|
|
||||||
|
uint64 fChange;
|
||||||
|
bigtime_t fExpireTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
DirectoryCache::Lock()
|
||||||
|
{
|
||||||
|
mutex_lock(&fLock);
|
||||||
|
if (fTrashed) {
|
||||||
|
mutex_unlock(&fLock);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
DirectoryCache::Unlock()
|
||||||
|
{
|
||||||
|
mutex_unlock(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline SinglyLinkedList<NameCacheEntry>&
|
||||||
|
DirectoryCache::EntriesList()
|
||||||
|
{
|
||||||
|
return fNameCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
DirectoryCache::ValidateChangeInfo(uint64 change)
|
||||||
|
{
|
||||||
|
if (fTrashed || change != fChange) {
|
||||||
|
Trash();
|
||||||
|
change = fChange;
|
||||||
|
fExpireTime = system_time() + kExpirationTime;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
DirectoryCache::SetChangeInfo(uint64 change)
|
||||||
|
{
|
||||||
|
fExpireTime = system_time() + kExpirationTime;
|
||||||
|
fChange = change;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint64
|
||||||
|
DirectoryCache::ChangeInfo()
|
||||||
|
{
|
||||||
|
return fChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Inode*
|
||||||
|
DirectoryCache::GetInode()
|
||||||
|
{
|
||||||
|
return fInode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline time_t
|
||||||
|
DirectoryCache::ExpireTime()
|
||||||
|
{
|
||||||
|
return fExpireTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DIRECTORYCACHE_H
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#define FILESYSTEM_H
|
#define FILESYSTEM_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "CacheRevalidator.h"
|
||||||
#include "InodeIdMap.h"
|
#include "InodeIdMap.h"
|
||||||
#include "NFS4Defs.h"
|
#include "NFS4Defs.h"
|
||||||
#include "NFS4Server.h"
|
#include "NFS4Server.h"
|
||||||
@@ -34,6 +35,8 @@ public:
|
|||||||
void AddOpenFile(OpenFileCookie* cookie);
|
void AddOpenFile(OpenFileCookie* cookie);
|
||||||
void RemoveOpenFile(OpenFileCookie* cookie);
|
void RemoveOpenFile(OpenFileCookie* cookie);
|
||||||
|
|
||||||
|
inline CacheRevalidator& Revalidator();
|
||||||
|
|
||||||
inline bool IsAttrSupported(Attribute attr) const;
|
inline bool IsAttrSupported(Attribute attr) const;
|
||||||
inline uint32 ExpireType() const;
|
inline uint32 ExpireType() const;
|
||||||
|
|
||||||
@@ -53,6 +56,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
FileSystem();
|
FileSystem();
|
||||||
|
|
||||||
|
CacheRevalidator fCacheRevalidator;
|
||||||
|
|
||||||
OpenFileCookie* fOpenFiles;
|
OpenFileCookie* fOpenFiles;
|
||||||
uint32 fOpenCount;
|
uint32 fOpenCount;
|
||||||
mutex fOpenLock;
|
mutex fOpenLock;
|
||||||
@@ -74,6 +79,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline CacheRevalidator&
|
||||||
|
FileSystem::Revalidator()
|
||||||
|
{
|
||||||
|
return fCacheRevalidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline RootInode*
|
inline RootInode*
|
||||||
FileSystem::Root()
|
FileSystem::Root()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
Inode::Inode()
|
Inode::Inode()
|
||||||
:
|
:
|
||||||
fAttrCacheExpire(0)
|
fAttrCacheExpire(0),
|
||||||
|
fCache(NULL)
|
||||||
{
|
{
|
||||||
mutex_init(&fAttrCacheLock, NULL);
|
mutex_init(&fAttrCacheLock, NULL);
|
||||||
}
|
}
|
||||||
@@ -80,6 +81,9 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
// FATTR4_TYPE is mandatory
|
// FATTR4_TYPE is mandatory
|
||||||
inode->fType = values[0].fData.fValue32;
|
inode->fType = values[0].fData.fValue32;
|
||||||
|
|
||||||
|
if (inode->fType == NF4DIR)
|
||||||
|
inode->fCache = new DirectoryCache(inode);
|
||||||
|
|
||||||
// FATTR4_FSID is mandatory
|
// FATTR4_FSID is mandatory
|
||||||
FileSystemId* fsid =
|
FileSystemId* fsid =
|
||||||
reinterpret_cast<FileSystemId*>(values[1].fData.fPointer);
|
reinterpret_cast<FileSystemId*>(values[1].fData.fPointer);
|
||||||
@@ -99,10 +103,50 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
|
|
||||||
Inode::~Inode()
|
Inode::~Inode()
|
||||||
{
|
{
|
||||||
|
delete fCache;
|
||||||
mutex_destroy(&fAttrCacheLock);
|
mutex_destroy(&fAttrCacheLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Inode::GetChangeInfo(uint64* change)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFileSystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
|
Attribute attr[] = { FATTR4_CHANGE };
|
||||||
|
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||||
|
|
||||||
|
status_t result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
if (_HandleErrors(reply.NFS4Error(), serv))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
reply.PutFH();
|
||||||
|
|
||||||
|
AttrValue* values;
|
||||||
|
uint32 count;
|
||||||
|
result = reply.GetAttr(&values, &count);
|
||||||
|
if (result != B_OK || count < 1)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// FATTR4_CHANGE is mandatory
|
||||||
|
*change = values[0].fData.fValue64;
|
||||||
|
delete[] values;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::LookUp(const char* name, ino_t* id)
|
Inode::LookUp(const char* name, ino_t* id)
|
||||||
{
|
{
|
||||||
@@ -121,6 +165,9 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
|
Attribute dirAttr[] = { FATTR4_CHANGE };
|
||||||
|
req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute));
|
||||||
|
|
||||||
if (!strcmp(name, ".."))
|
if (!strcmp(name, ".."))
|
||||||
req.LookUpUp();
|
req.LookUpUp();
|
||||||
else
|
else
|
||||||
@@ -141,6 +188,16 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
|
|
||||||
|
AttrValue* values;
|
||||||
|
uint32 count;
|
||||||
|
result = reply.GetAttr(&values, &count);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
uint64 change = values[0].fData.fValue64;
|
||||||
|
delete[] values;
|
||||||
|
|
||||||
if (!strcmp(name, ".."))
|
if (!strcmp(name, ".."))
|
||||||
result = reply.LookUpUp();
|
result = reply.LookUpUp();
|
||||||
else
|
else
|
||||||
@@ -151,8 +208,6 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
FileHandle fh;
|
FileHandle fh;
|
||||||
reply.GetFH(&fh);
|
reply.GetFH(&fh);
|
||||||
|
|
||||||
AttrValue* values;
|
|
||||||
uint32 count;
|
|
||||||
result = reply.GetAttr(&values, &count);
|
result = reply.GetAttr(&values, &count);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -194,6 +249,20 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
|
|
||||||
fFileSystem->InoIdMap()->AddEntry(fi, *id);
|
fFileSystem->InoIdMap()->AddEntry(fi, *id);
|
||||||
|
|
||||||
|
fFileSystem->Revalidator().Lock();
|
||||||
|
if (fCache->Lock() != B_OK) {
|
||||||
|
fCache->ResetAndLock();
|
||||||
|
fCache->SetChangeInfo(change);
|
||||||
|
} else {
|
||||||
|
fFileSystem->Revalidator().RemoveDirectory(fCache);
|
||||||
|
fCache->ValidateChangeInfo(change);
|
||||||
|
}
|
||||||
|
|
||||||
|
fCache->AddEntry(name, *id);
|
||||||
|
fFileSystem->Revalidator().AddDirectory(fCache);
|
||||||
|
fCache->Unlock();
|
||||||
|
fFileSystem->Revalidator().Unlock();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
@@ -294,6 +363,8 @@ Inode::Remove(const char* name, FileType type)
|
|||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
result = reply.Remove();
|
result = reply.Remove();
|
||||||
|
|
||||||
|
// remove entry
|
||||||
|
|
||||||
fFileSystem->Root()->MakeInfoInvalid();
|
fFileSystem->Root()->MakeInfoInvalid();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -344,7 +415,11 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName)
|
|||||||
reply.SaveFH();
|
reply.SaveFH();
|
||||||
reply.PutFH();
|
reply.PutFH();
|
||||||
|
|
||||||
return reply.Rename();
|
result = reply.Rename();
|
||||||
|
|
||||||
|
// remove entry
|
||||||
|
|
||||||
|
return result;
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ public:
|
|||||||
inline const char* Name() const;
|
inline const char* Name() const;
|
||||||
inline FileSystem* GetFileSystem() const;
|
inline FileSystem* GetFileSystem() const;
|
||||||
|
|
||||||
|
status_t GetChangeInfo(uint64* change);
|
||||||
|
|
||||||
status_t LookUp(const char* name, ino_t* id);
|
status_t LookUp(const char* name, ino_t* id);
|
||||||
|
|
||||||
status_t CreateLink(const char* name, const char* path,
|
status_t CreateLink(const char* name, const char* path,
|
||||||
@@ -99,6 +101,8 @@ protected:
|
|||||||
|
|
||||||
FileInfo fInfo;
|
FileInfo fInfo;
|
||||||
FileSystem* fFileSystem;
|
FileSystem* fFileSystem;
|
||||||
|
|
||||||
|
DirectoryCache* fCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ UsePrivateKernelHeaders ;
|
|||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
KernelAddon nfs4 :
|
KernelAddon nfs4 :
|
||||||
|
CacheRevalidator.cpp
|
||||||
Cookie.cpp
|
Cookie.cpp
|
||||||
Connection.cpp
|
Connection.cpp
|
||||||
|
DirectoryCache.cpp
|
||||||
FileInfo.cpp
|
FileInfo.cpp
|
||||||
FileSystem.cpp
|
FileSystem.cpp
|
||||||
IdMap.cpp
|
IdMap.cpp
|
||||||
|
|||||||
@@ -528,6 +528,12 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
|||||||
current++;
|
current++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sIsAttrSet(FATTR4_CHANGE, bitmap, bcount)) {
|
||||||
|
values[current].fAttribute = FATTR4_CHANGE;
|
||||||
|
values[current].fData.fValue64 = stream.GetUHyper();
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
if (sIsAttrSet(FATTR4_SIZE, bitmap, bcount)) {
|
if (sIsAttrSet(FATTR4_SIZE, bitmap, bcount)) {
|
||||||
values[current].fAttribute = FATTR4_SIZE;
|
values[current].fAttribute = FATTR4_SIZE;
|
||||||
values[current].fData.fValue64 = stream.GetUHyper();
|
values[current].fData.fValue64 = stream.GetUHyper();
|
||||||
|
|||||||
Reference in New Issue
Block a user