nfs4: Reclaim delegations after server reboot
This commit is contained in:
@@ -57,6 +57,14 @@ LockInfo::operator==(const struct flock& lock) const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LockInfo::operator==(const LockInfo& lock) const
|
||||
{
|
||||
return fOwner == lock.fOwner && fStart == lock.fStart
|
||||
&& fLength == lock.fLength && fType == lock.fType;
|
||||
}
|
||||
|
||||
|
||||
Cookie::Cookie()
|
||||
:
|
||||
fRequests(NULL),
|
||||
@@ -131,102 +139,26 @@ Cookie::CancelAll()
|
||||
|
||||
OpenFileCookie::OpenFileCookie()
|
||||
:
|
||||
fLocks(NULL),
|
||||
fLockOwners(NULL)
|
||||
fLocks(NULL)
|
||||
{
|
||||
mutex_init(&fLocksLock, NULL);
|
||||
mutex_init(&fOwnerLock, NULL);
|
||||
}
|
||||
|
||||
|
||||
OpenFileCookie::~OpenFileCookie()
|
||||
{
|
||||
mutex_destroy(&fLocksLock);
|
||||
mutex_destroy(&fOwnerLock);
|
||||
}
|
||||
|
||||
|
||||
LockOwner*
|
||||
OpenFileCookie::GetLockOwner(uint32 owner)
|
||||
{
|
||||
LockOwner* current = fLockOwners;
|
||||
while (current != NULL) {
|
||||
if (current->fOwner == owner)
|
||||
return current;
|
||||
|
||||
current = current->fNext;
|
||||
}
|
||||
|
||||
current = new LockOwner(owner);
|
||||
if (current == NULL)
|
||||
return NULL;
|
||||
|
||||
current->fNext = fLockOwners;
|
||||
if (fLockOwners != NULL)
|
||||
fLockOwners->fPrev = current;
|
||||
fLockOwners = current;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
// Caller must hold fLocksLock
|
||||
void
|
||||
OpenFileCookie::AddLock(LockInfo* lock)
|
||||
{
|
||||
lock->fNext = fLocks;
|
||||
lock->fCookieNext = fLocks;
|
||||
fLocks = lock;
|
||||
}
|
||||
|
||||
|
||||
// Caller must hold fLocksLock
|
||||
void
|
||||
OpenFileCookie::RemoveLock(LockInfo* lock, LockInfo* prev)
|
||||
{
|
||||
if (prev != NULL)
|
||||
prev->fNext = lock->fNext;
|
||||
prev->fCookieNext = lock->fCookieNext;
|
||||
else
|
||||
fLocks = lock->fNext;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OpenFileCookie::DeleteLock(LockInfo* lock)
|
||||
{
|
||||
MutexLocker _(fOwnerLock);
|
||||
|
||||
LockOwner* owner = lock->fOwner;
|
||||
delete lock;
|
||||
|
||||
if (owner->fUseCount == 0) {
|
||||
if (owner->fPrev)
|
||||
owner->fPrev->fNext = owner->fNext;
|
||||
else
|
||||
fLockOwners = owner->fNext;
|
||||
if (owner->fNext)
|
||||
owner->fNext->fPrev = owner->fPrev;
|
||||
|
||||
_ReleaseLockOwner(owner);
|
||||
delete owner;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OpenFileCookie::_ReleaseLockOwner(LockOwner* owner)
|
||||
{
|
||||
Request request(fFileSystem->Server());
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.ReleaseLockOwner(this, owner);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
ReplyInterpreter &reply = request.Reply();
|
||||
|
||||
return reply.ReleaseLockOwner();
|
||||
fLocks = lock->fCookieNext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "OpenState.h"
|
||||
|
||||
|
||||
struct OpenState;
|
||||
|
||||
struct LockOwner {
|
||||
uint64 fClientId;
|
||||
|
||||
@@ -43,11 +44,13 @@ struct LockInfo {
|
||||
LockType fType;
|
||||
|
||||
LockInfo* fNext;
|
||||
LockInfo* fCookieNext;
|
||||
|
||||
LockInfo(LockOwner* owner);
|
||||
~LockInfo();
|
||||
|
||||
bool operator==(const struct flock& lock) const;
|
||||
bool operator==(const LockInfo& lock) const;
|
||||
};
|
||||
|
||||
struct Cookie {
|
||||
@@ -76,25 +79,11 @@ struct OpenFileCookie : public Cookie {
|
||||
uint32 fMode;
|
||||
|
||||
LockInfo* fLocks;
|
||||
mutex fLocksLock;
|
||||
|
||||
LockOwner* fLockOwners;
|
||||
mutex fOwnerLock;
|
||||
|
||||
OpenFileCookie* fNext;
|
||||
OpenFileCookie* fPrev;
|
||||
|
||||
OpenFileCookie();
|
||||
~OpenFileCookie();
|
||||
|
||||
LockOwner* GetLockOwner(uint32 owner);
|
||||
|
||||
void AddLock(LockInfo* lock);
|
||||
void RemoveLock(LockInfo* lock, LockInfo* prev);
|
||||
void DeleteLock(LockInfo* lock);
|
||||
|
||||
private:
|
||||
status_t _ReleaseLockOwner(LockOwner* owner);
|
||||
OpenFileCookie();
|
||||
};
|
||||
|
||||
struct OpenDirCookie : public Cookie {
|
||||
|
||||
@@ -24,16 +24,12 @@ public:
|
||||
uint64 clientID);
|
||||
~Delegation();
|
||||
|
||||
status_t Write(void* buffer, uint32* size);
|
||||
status_t Read(void* buffer, uint32* size);
|
||||
|
||||
// TODO: locks
|
||||
|
||||
status_t Reclaim(uint64 newClientID);
|
||||
|
||||
status_t GiveUp(bool truncate);
|
||||
status_t GiveUp(bool truncate = false);
|
||||
|
||||
inline Inode* GetInode();
|
||||
inline OpenDelegation Type();
|
||||
|
||||
protected:
|
||||
status_t ReturnDelegation();
|
||||
@@ -54,5 +50,12 @@ Delegation::GetInode()
|
||||
}
|
||||
|
||||
|
||||
inline OpenDelegation
|
||||
Delegation::Type()
|
||||
{
|
||||
return fData.fType;
|
||||
}
|
||||
|
||||
|
||||
#endif // DELEGATION_H
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ FileSystem::Migrate(const RPC::Server* serv)
|
||||
}
|
||||
|
||||
|
||||
OpenFileCookie*
|
||||
OpenState*
|
||||
FileSystem::OpenFilesLock()
|
||||
{
|
||||
mutex_lock(&fOpenLock);
|
||||
@@ -283,30 +283,30 @@ FileSystem::OpenFilesUnlock()
|
||||
|
||||
|
||||
void
|
||||
FileSystem::AddOpenFile(OpenFileCookie* cookie)
|
||||
FileSystem::AddOpenFile(OpenState* state)
|
||||
{
|
||||
MutexLocker _(fOpenLock);
|
||||
|
||||
cookie->fPrev = NULL;
|
||||
cookie->fNext = fOpenFiles;
|
||||
state->fPrev = NULL;
|
||||
state->fNext = fOpenFiles;
|
||||
if (fOpenFiles != NULL)
|
||||
fOpenFiles->fPrev = cookie;
|
||||
fOpenFiles = cookie;
|
||||
fOpenFiles->fPrev = state;
|
||||
fOpenFiles = state;
|
||||
NFSServer()->IncUsage();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FileSystem::RemoveOpenFile(OpenFileCookie* cookie)
|
||||
FileSystem::RemoveOpenFile(OpenState* state)
|
||||
{
|
||||
MutexLocker _(fOpenLock);
|
||||
if (cookie == fOpenFiles)
|
||||
fOpenFiles = cookie->fNext;
|
||||
if (state == fOpenFiles)
|
||||
fOpenFiles = state->fNext;
|
||||
|
||||
if (cookie->fNext)
|
||||
cookie->fNext->fPrev = cookie->fPrev;
|
||||
if (cookie->fPrev)
|
||||
cookie->fPrev->fNext = cookie->fNext;
|
||||
if (state->fNext)
|
||||
state->fNext->fPrev = state->fPrev;
|
||||
if (state->fPrev)
|
||||
state->fPrev->fNext = state->fNext;
|
||||
NFSServer()->DecUsage();
|
||||
}
|
||||
|
||||
@@ -316,8 +316,6 @@ FileSystem::AddDelegation(Delegation* delegation)
|
||||
{
|
||||
MutexLocker _(fDelegationLock);
|
||||
|
||||
fOpenDelegations.InsertBefore(fOpenDelegations.Head(), delegation);
|
||||
|
||||
fHandleToDelegation.Remove(delegation->fInfo.fHandle);
|
||||
fHandleToDelegation.Insert(delegation->fInfo.fHandle, delegation);
|
||||
|
||||
@@ -330,7 +328,6 @@ FileSystem::RemoveDelegation(Delegation* delegation)
|
||||
{
|
||||
MutexLocker _(fDelegationLock);
|
||||
|
||||
fOpenDelegations.Remove(delegation);
|
||||
fHandleToDelegation.Remove(delegation->fInfo.fHandle);
|
||||
|
||||
NFSServer()->DecUsage();
|
||||
|
||||
@@ -30,14 +30,12 @@ public:
|
||||
|
||||
status_t Migrate(const RPC::Server* serv);
|
||||
|
||||
OpenFileCookie* OpenFilesLock();
|
||||
OpenState* OpenFilesLock();
|
||||
void OpenFilesUnlock();
|
||||
inline uint32 OpenFilesCount();
|
||||
void AddOpenFile(OpenFileCookie* cookie);
|
||||
void RemoveOpenFile(OpenFileCookie* cookie);
|
||||
void AddOpenFile(OpenState* state);
|
||||
void RemoveOpenFile(OpenState* state);
|
||||
|
||||
OpenFileCookie* DelegationsLock();
|
||||
void DelegationsUnlock();
|
||||
void AddDelegation(Delegation* delegation);
|
||||
void RemoveDelegation(Delegation* delegation);
|
||||
Delegation* GetDelegation(const FileHandle& handle);
|
||||
@@ -69,11 +67,10 @@ private:
|
||||
|
||||
CacheRevalidator fCacheRevalidator;
|
||||
|
||||
DoublyLinkedList<Delegation> fOpenDelegations;
|
||||
mutex fDelegationLock;
|
||||
AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation;
|
||||
|
||||
OpenFileCookie* fOpenFiles;
|
||||
OpenState* fOpenFiles;
|
||||
uint32 fOpenCount;
|
||||
mutex fOpenLock;
|
||||
|
||||
|
||||
@@ -607,6 +607,8 @@ status_t
|
||||
Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock,
|
||||
bool wait)
|
||||
{
|
||||
OpenState* state = cookie->fOpenState;
|
||||
|
||||
status_t result = CheckLockType(lock->l_type, cookie->fMode);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
@@ -614,8 +616,8 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock,
|
||||
thread_info info;
|
||||
get_thread_info(find_thread(NULL), &info);
|
||||
|
||||
MutexLocker locker(cookie->fOwnerLock);
|
||||
LockOwner* owner = cookie->GetLockOwner(info.team);
|
||||
MutexLocker locker(state->fOwnerLock);
|
||||
LockOwner* owner = state->GetLockOwner(info.team);
|
||||
if (owner == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -635,7 +637,8 @@ Inode::AcquireLock(OpenFileCookie* cookie, const struct flock* lock,
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
MutexLocker _(cookie->fLocksLock);
|
||||
MutexLocker _(state->fLocksLock);
|
||||
state->AddLock(linfo);
|
||||
cookie->AddLock(linfo);
|
||||
|
||||
return B_OK;
|
||||
@@ -654,8 +657,21 @@ Inode::ReleaseLock(OpenFileCookie* cookie, const struct flock* lock)
|
||||
get_thread_info(find_thread(NULL), &info);
|
||||
uint32 owner = info.team;
|
||||
|
||||
MutexLocker locker(cookie->fLocksLock);
|
||||
LockInfo* linfo = cookie->fLocks;
|
||||
OpenState* state = cookie->fOpenState;
|
||||
MutexLocker locker(state->fLocksLock);
|
||||
LockInfo* linfo = state->fLocks;
|
||||
while (linfo != NULL) {
|
||||
if (linfo->fOwner->fOwner == owner && *linfo == *lock) {
|
||||
state->RemoveLock(linfo, prev);
|
||||
break;
|
||||
}
|
||||
|
||||
prev = linfo;
|
||||
linfo = linfo->fNext;
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
linfo = cookie->fLocks;
|
||||
while (linfo != NULL) {
|
||||
if (linfo->fOwner->fOwner == owner && *linfo == *lock) {
|
||||
cookie->RemoveLock(linfo, prev);
|
||||
@@ -663,7 +679,7 @@ Inode::ReleaseLock(OpenFileCookie* cookie, const struct flock* lock)
|
||||
}
|
||||
|
||||
prev = linfo;
|
||||
linfo = linfo->fNext;
|
||||
linfo = linfo->fCookieNext;
|
||||
}
|
||||
locker.Unlock();
|
||||
|
||||
@@ -674,7 +690,7 @@ Inode::ReleaseLock(OpenFileCookie* cookie, const struct flock* lock)
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
cookie->DeleteLock(linfo);
|
||||
state->DeleteLock(linfo);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -686,12 +702,26 @@ Inode::ReleaseAllLocks(OpenFileCookie* cookie)
|
||||
file_cache_sync(fFileCache);
|
||||
Commit();
|
||||
|
||||
MutexLocker _(cookie->fLocksLock);
|
||||
OpenState* state = cookie->fOpenState;
|
||||
MutexLocker _(state->fLocksLock);
|
||||
LockInfo* linfo = cookie->fLocks;
|
||||
while (linfo != NULL) {
|
||||
NFS4Inode::ReleaseLock(cookie, linfo);
|
||||
cookie->RemoveLock(linfo, NULL);
|
||||
cookie->DeleteLock(linfo);
|
||||
|
||||
LockInfo* prev = NULL;
|
||||
LockInfo* stateLock = state->fLocks;
|
||||
while (stateLock != NULL) {
|
||||
if (*linfo == *stateLock) {
|
||||
state->RemoveLock(stateLock, prev);
|
||||
break;
|
||||
}
|
||||
|
||||
prev = stateLock;
|
||||
stateLock = stateLock->fNext;
|
||||
}
|
||||
|
||||
NFS4Inode::ReleaseLock(cookie, linfo);
|
||||
state->DeleteLock(linfo);
|
||||
|
||||
linfo = cookie->fLocks;
|
||||
}
|
||||
@@ -733,6 +763,8 @@ Inode::SetDelegation(Delegation* delegation)
|
||||
{
|
||||
WriteLocker _(fDelegationLock);
|
||||
fDelegation = delegation;
|
||||
fOpenState->AcquireReference();
|
||||
fOpenState->fDelegation = delegation;
|
||||
fFileSystem->AddDelegation(delegation);
|
||||
}
|
||||
|
||||
@@ -746,6 +778,14 @@ Inode::RecallDelegation(bool truncate)
|
||||
|
||||
fDelegation->GiveUp(truncate);
|
||||
fFileSystem->RemoveDelegation(fDelegation);
|
||||
|
||||
MutexLocker stateLocker(fStateLock);
|
||||
fOpenState->fDelegation = NULL;
|
||||
if (fOpenState->ReleaseReference() == 1) {
|
||||
fFileSystem->RemoveOpenFile(fOpenState);
|
||||
fOpenState = NULL;
|
||||
}
|
||||
|
||||
delete fDelegation;
|
||||
fDelegation = NULL;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
|
||||
|
||||
cookie->fFileSystem = fFileSystem;
|
||||
|
||||
fFileSystem->AddOpenFile(cookie);
|
||||
fFileSystem->AddOpenFile(state);
|
||||
fFileSystem->Root()->MakeInfoInvalid();
|
||||
|
||||
return B_OK;
|
||||
@@ -109,6 +109,7 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
fFileSystem->AddOpenFile(state);
|
||||
fOpenState = state;
|
||||
} else {
|
||||
int newMode = mode & O_RWMASK;
|
||||
@@ -128,8 +129,6 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
||||
cookie->fMode = mode;
|
||||
cookie->fLocks = NULL;
|
||||
|
||||
fFileSystem->AddOpenFile(cookie);
|
||||
|
||||
if (data.fType != OPEN_DELEGATE_NONE) {
|
||||
Delegation* delegation
|
||||
= new(std::nothrow) Delegation(data, this, fOpenState->fClientID);
|
||||
@@ -150,12 +149,13 @@ Inode::Close(OpenFileCookie* cookie)
|
||||
file_cache_sync(fFileCache);
|
||||
Commit();
|
||||
|
||||
fFileSystem->RemoveOpenFile(cookie);
|
||||
|
||||
MutexLocker _(fStateLock);
|
||||
if (cookie->fOpenState != NULL)
|
||||
if (cookie->fOpenState->ReleaseReference() == 1)
|
||||
if (cookie->fOpenState != NULL) {
|
||||
if (cookie->fOpenState->ReleaseReference() == 1) {
|
||||
fFileSystem->RemoveOpenFile(fOpenState);
|
||||
fOpenState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -879,7 +879,7 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* type, uint64* position,
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
req.LockT(*type, *position, *length, cookie);
|
||||
req.LockT(*type, *position, *length, cookie->fOpenState);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK)
|
||||
@@ -916,7 +916,7 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait)
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
req.Lock(cookie, lockInfo, sequence);
|
||||
req.Lock(cookie->fOpenState, lockInfo, sequence);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Cookie.h"
|
||||
#include "FileSystem.h"
|
||||
#include "NFS4Object.h"
|
||||
#include "OpenState.h"
|
||||
#include "Request.h"
|
||||
|
||||
|
||||
|
||||
@@ -57,13 +57,14 @@ NFS4Server::ServerRebooted(uint64 clientId)
|
||||
MutexLocker _(fFSLock);
|
||||
FileSystem* fs = fFileSystems;
|
||||
while (fs != NULL) {
|
||||
OpenFileCookie* current = fs->OpenFilesLock();
|
||||
OpenState* current = fs->OpenFilesLock();
|
||||
while (current != NULL) {
|
||||
_ReclaimOpen(current);
|
||||
_ReclaimLocks(current);
|
||||
current->Reclaim(fClientId);
|
||||
|
||||
current = current->fNext;
|
||||
}
|
||||
fs->OpenFilesUnlock();
|
||||
|
||||
fs = fs->fNext;
|
||||
}
|
||||
|
||||
@@ -71,55 +72,6 @@ NFS4Server::ServerRebooted(uint64 clientId)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::_ReclaimOpen(OpenFileCookie* cookie)
|
||||
{
|
||||
if (cookie->fOpenState != NULL)
|
||||
cookie->fOpenState->Reclaim(fClientId);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NFS4Server::_ReclaimLocks(OpenFileCookie* cookie)
|
||||
{
|
||||
MutexLocker _(cookie->fLocksLock);
|
||||
LockInfo* linfo = cookie->fLocks;
|
||||
while (linfo != NULL) {
|
||||
MutexLocker locker(linfo->fOwner->fLock);
|
||||
if (linfo->fOwner->fClientId != fClientId) {
|
||||
memset(linfo->fOwner->fStateId, 0, sizeof(linfo->fOwner->fStateId));
|
||||
linfo->fOwner->fClientId = fClientId;
|
||||
}
|
||||
|
||||
do {
|
||||
Request request(fServer);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(cookie->fOpenState->fInfo.fHandle);
|
||||
req.Lock(cookie, linfo, true);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK)
|
||||
break;
|
||||
|
||||
ReplyInterpreter &reply = request.Reply();
|
||||
|
||||
reply.PutFH();
|
||||
reply.Lock(linfo);
|
||||
|
||||
break;
|
||||
} while (true);
|
||||
locker.Unlock();
|
||||
|
||||
linfo = linfo->fNext;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NFS4Server::AddFileSystem(FileSystem* fs)
|
||||
{
|
||||
|
||||
@@ -43,9 +43,6 @@ public:
|
||||
status_t CallbackRecall(RequestInterpreter* request,
|
||||
ReplyBuilder* reply);
|
||||
private:
|
||||
status_t _ReclaimOpen(OpenFileCookie* cookie);
|
||||
status_t _ReclaimLocks(OpenFileCookie* cookie);
|
||||
|
||||
status_t _GetLeaseTime();
|
||||
|
||||
status_t _StartRenewing();
|
||||
|
||||
@@ -17,9 +17,15 @@
|
||||
|
||||
OpenState::OpenState()
|
||||
:
|
||||
fOpened(false)
|
||||
fOpened(false),
|
||||
fDelegation(NULL),
|
||||
fLocks(NULL),
|
||||
fLockOwners(NULL)
|
||||
{
|
||||
mutex_init(&fLock, NULL);
|
||||
|
||||
mutex_init(&fLocksLock, NULL);
|
||||
mutex_init(&fOwnerLock, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +33,99 @@ OpenState::~OpenState()
|
||||
{
|
||||
Close();
|
||||
mutex_destroy(&fLock);
|
||||
|
||||
mutex_destroy(&fLocksLock);
|
||||
mutex_destroy(&fOwnerLock);
|
||||
}
|
||||
|
||||
|
||||
LockOwner*
|
||||
OpenState::GetLockOwner(uint32 owner)
|
||||
{
|
||||
LockOwner* current = fLockOwners;
|
||||
while (current != NULL) {
|
||||
if (current->fOwner == owner)
|
||||
return current;
|
||||
|
||||
current = current->fNext;
|
||||
}
|
||||
|
||||
current = new LockOwner(owner);
|
||||
if (current == NULL)
|
||||
return NULL;
|
||||
|
||||
current->fNext = fLockOwners;
|
||||
if (fLockOwners != NULL)
|
||||
fLockOwners->fPrev = current;
|
||||
fLockOwners = current;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
// Caller must hold fLocksLock
|
||||
void
|
||||
OpenState::AddLock(LockInfo* lock)
|
||||
{
|
||||
lock->fNext = fLocks;
|
||||
fLocks = lock;
|
||||
}
|
||||
|
||||
|
||||
// Caller must hold fLocksLock
|
||||
void
|
||||
OpenState::RemoveLock(LockInfo* lock, LockInfo* prev)
|
||||
{
|
||||
if (prev != NULL)
|
||||
prev->fNext = lock->fNext;
|
||||
else
|
||||
fLocks = lock->fNext;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OpenState::DeleteLock(LockInfo* lock)
|
||||
{
|
||||
MutexLocker _(fOwnerLock);
|
||||
|
||||
LockOwner* owner = lock->fOwner;
|
||||
delete lock;
|
||||
|
||||
if (owner->fUseCount == 0) {
|
||||
if (owner->fPrev)
|
||||
owner->fPrev->fNext = owner->fNext;
|
||||
else
|
||||
fLockOwners = owner->fNext;
|
||||
if (owner->fNext)
|
||||
owner->fNext->fPrev = owner->fPrev;
|
||||
|
||||
_ReleaseLockOwner(owner);
|
||||
delete owner;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OpenState::_ReleaseLockOwner(LockOwner* owner)
|
||||
{
|
||||
do {
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.ReleaseLockOwner(this, owner);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
ReplyInterpreter &reply = request.Reply();
|
||||
|
||||
if (HandleErrors(reply.NFS4Error(), server))
|
||||
continue;
|
||||
|
||||
return reply.ReleaseLockOwner();
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +141,15 @@ OpenState::Reclaim(uint64 newClientID)
|
||||
return B_OK;
|
||||
fClientID = newClientID;
|
||||
|
||||
_ReclaimOpen(newClientID);
|
||||
_ReclaimLocks(newClientID);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OpenState::_ReclaimOpen(uint64 newClientID)
|
||||
{
|
||||
bool confirm;
|
||||
OpenDelegationData delegation;
|
||||
|
||||
@@ -53,7 +161,8 @@ OpenState::Reclaim(uint64 newClientID)
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
req.Open(CLAIM_PREVIOUS, sequence, sModeToAccess(fMode), newClientID,
|
||||
OPEN4_NOCREATE, fFileSystem->OpenOwner(), NULL);
|
||||
OPEN4_NOCREATE, fFileSystem->OpenOwner(), NULL, NULL, 0, false,
|
||||
fDelegation->Type());
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK) {
|
||||
@@ -75,6 +184,9 @@ OpenState::Reclaim(uint64 newClientID)
|
||||
return result;
|
||||
} while (true);
|
||||
|
||||
if (delegation.fRecall)
|
||||
fDelegation->GiveUp();
|
||||
|
||||
if (confirm)
|
||||
return ConfirmOpen(fInfo.fHandle, this);
|
||||
|
||||
@@ -82,6 +194,50 @@ OpenState::Reclaim(uint64 newClientID)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OpenState::_ReclaimLocks(uint64 newClientID)
|
||||
{
|
||||
MutexLocker _(fLocksLock);
|
||||
LockInfo* linfo = fLocks;
|
||||
while (linfo != NULL) {
|
||||
MutexLocker locker(linfo->fOwner->fLock);
|
||||
|
||||
if (linfo->fOwner->fClientId != newClientID) {
|
||||
memset(linfo->fOwner->fStateId, 0, sizeof(linfo->fOwner->fStateId));
|
||||
linfo->fOwner->fClientId = newClientID;
|
||||
}
|
||||
|
||||
do {
|
||||
RPC::Server* server = fFileSystem->Server();
|
||||
Request request(server);
|
||||
RequestBuilder& req = request.Builder();
|
||||
|
||||
req.PutFH(fInfo.fHandle);
|
||||
req.Lock(this, linfo, true);
|
||||
|
||||
status_t result = request.Send();
|
||||
if (result != B_OK)
|
||||
break;
|
||||
|
||||
ReplyInterpreter &reply = request.Reply();
|
||||
|
||||
if (HandleErrors(reply.NFS4Error(), server))
|
||||
continue;
|
||||
|
||||
reply.PutFH();
|
||||
reply.Lock(linfo);
|
||||
|
||||
break;
|
||||
} while (true);
|
||||
locker.Unlock();
|
||||
|
||||
linfo = linfo->fNext;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OpenState::Close()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <SupportDefs.h>
|
||||
#include <util/KernelReferenceable.h>
|
||||
|
||||
#include "Cookie.h"
|
||||
#include "NFS4Object.h"
|
||||
|
||||
|
||||
@@ -29,10 +30,31 @@ struct OpenState : public NFS4Object, public KernelReferenceable {
|
||||
uint32 fStateSeq;
|
||||
|
||||
bool fOpened;
|
||||
Delegation* fDelegation;
|
||||
|
||||
LockInfo* fLocks;
|
||||
mutex fLocksLock;
|
||||
|
||||
LockOwner* fLockOwners;
|
||||
mutex fOwnerLock;
|
||||
|
||||
OpenState* fNext;
|
||||
OpenState* fPrev;
|
||||
|
||||
LockOwner* GetLockOwner(uint32 owner);
|
||||
|
||||
void AddLock(LockInfo* lock);
|
||||
void RemoveLock(LockInfo* lock, LockInfo* prev);
|
||||
void DeleteLock(LockInfo* lock);
|
||||
|
||||
status_t Reclaim(uint64 newClientID);
|
||||
|
||||
status_t Close();
|
||||
|
||||
private:
|
||||
status_t _ReclaimOpen(uint64 newClientID);
|
||||
status_t _ReclaimLocks(uint64 newClientID);
|
||||
status_t _ReleaseLockOwner(LockOwner* owner);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "Cookie.h"
|
||||
#include "OpenState.h"
|
||||
#include "RPCCallback.h"
|
||||
#include "RPCCallbackServer.h"
|
||||
|
||||
@@ -192,19 +193,19 @@ RequestBuilder::GetFH()
|
||||
|
||||
void
|
||||
RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream,
|
||||
OpenFileCookie* cookie, LockOwner* owner)
|
||||
OpenState* state, LockOwner* owner)
|
||||
{
|
||||
stream.AddUHyper(cookie->fOpenState->fClientID);
|
||||
stream.AddUHyper(state->fClientID);
|
||||
|
||||
uint64 lockOwner[2];
|
||||
lockOwner[0] = owner->fOwner;
|
||||
lockOwner[1] = cookie->fOpenState->fInfo.fFileId;
|
||||
lockOwner[1] = state->fInfo.fFileId;
|
||||
stream.AddOpaque(lockOwner, sizeof(lockOwner));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence,
|
||||
RequestBuilder::Lock(OpenState* state, LockInfo* lock, uint32 sequence,
|
||||
bool reclaim)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
@@ -226,8 +227,6 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence,
|
||||
fRequest->Stream().AddBoolean(true); // new lock owner
|
||||
|
||||
// open seq stateid
|
||||
OpenState* state = cookie->fOpenState;
|
||||
|
||||
fRequest->Stream().AddUInt(sequence);
|
||||
fRequest->Stream().AddUInt(state->fStateSeq);
|
||||
fRequest->Stream().AddUInt(state->fStateID[0]);
|
||||
@@ -236,7 +235,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence,
|
||||
|
||||
// lock seq owner
|
||||
fRequest->Stream().AddUInt(lock->fOwner->fSequence++);
|
||||
_GenerateLockOwner(fRequest->Stream(), cookie, lock->fOwner);
|
||||
_GenerateLockOwner(fRequest->Stream(), state, lock->fOwner);
|
||||
|
||||
} else {
|
||||
fRequest->Stream().AddBoolean(false); // old lock owner
|
||||
@@ -258,7 +257,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence,
|
||||
|
||||
status_t
|
||||
RequestBuilder::LockT(LockType type, uint64 pos, uint64 len,
|
||||
OpenFileCookie* cookie)
|
||||
OpenState* state)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
@@ -272,7 +271,7 @@ RequestBuilder::LockT(LockType type, uint64 pos, uint64 len,
|
||||
fRequest->Stream().AddUHyper(pos);
|
||||
fRequest->Stream().AddUHyper(len);
|
||||
|
||||
fRequest->Stream().AddUHyper(cookie->fOpenState->fClientID);
|
||||
fRequest->Stream().AddUHyper(state->fClientID);
|
||||
|
||||
uint32 owner = find_thread(NULL);
|
||||
fRequest->Stream().AddOpaque(&owner, sizeof(owner));
|
||||
@@ -381,7 +380,7 @@ RequestBuilder::Nverify(AttrValue* attr, uint32 count)
|
||||
status_t
|
||||
RequestBuilder::Open(OpenClaim claim, uint32 seq, uint32 access, uint64 id,
|
||||
OpenCreate oc, uint64 ownerId, const char* name, AttrValue* attr,
|
||||
uint32 count, bool excl)
|
||||
uint32 count, bool excl, OpenDelegation delegationType)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
@@ -413,7 +412,7 @@ RequestBuilder::Open(OpenClaim claim, uint32 seq, uint32 access, uint64 id,
|
||||
fRequest->Stream().AddString(name, strlen(name));
|
||||
break;
|
||||
case CLAIM_PREVIOUS:
|
||||
fRequest->Stream().AddUInt(0);
|
||||
fRequest->Stream().AddUInt(delegationType);
|
||||
break;
|
||||
default:
|
||||
return B_UNSUPPORTED;
|
||||
@@ -795,7 +794,7 @@ RequestBuilder::Write(const uint32* id, uint32 stateSeq, const void* buffer,
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::ReleaseLockOwner(OpenFileCookie* cookie, LockOwner* owner)
|
||||
RequestBuilder::ReleaseLockOwner(OpenState* state, LockOwner* owner)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
@@ -803,7 +802,7 @@ RequestBuilder::ReleaseLockOwner(OpenFileCookie* cookie, LockOwner* owner)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpReleaseLockOwner);
|
||||
_GenerateLockOwner(fRequest->Stream(), cookie, owner);
|
||||
_GenerateLockOwner(fRequest->Stream(), state, owner);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "XDR.h"
|
||||
|
||||
|
||||
class OpenFileCookie;
|
||||
class OpenState;
|
||||
class LockInfo;
|
||||
class LockOwner;
|
||||
|
||||
@@ -41,11 +41,10 @@ public:
|
||||
status_t GetAttr(Attribute* attrs, uint32 count);
|
||||
status_t GetFH();
|
||||
status_t Link(const char* name);
|
||||
status_t Lock(OpenFileCookie* cookie,
|
||||
LockInfo* lock, uint32 sequence,
|
||||
bool reclaim = false);
|
||||
status_t Lock(OpenState* state, LockInfo* lock,
|
||||
uint32 sequence, bool reclaim = false);
|
||||
status_t LockT(LockType type, uint64 pos,
|
||||
uint64 len, OpenFileCookie* cookie);
|
||||
uint64 len, OpenState* state);
|
||||
status_t LockU(LockInfo* lock);
|
||||
status_t LookUp(const char* name);
|
||||
status_t LookUpUp();
|
||||
@@ -54,7 +53,9 @@ public:
|
||||
uint32 access, uint64 id, OpenCreate oc,
|
||||
uint64 ownerId, const char* name,
|
||||
AttrValue* attr = NULL,
|
||||
uint32 count = 0, bool excl = false);
|
||||
uint32 count = 0, bool excl = false,
|
||||
OpenDelegation delegType
|
||||
= OPEN_DELEGATE_NONE);
|
||||
status_t OpenConfirm(uint32 seq, const uint32* id,
|
||||
uint32 stateSeq);
|
||||
status_t PutFH(const FileHandle& fh);
|
||||
@@ -77,7 +78,7 @@ public:
|
||||
status_t Write(const uint32* id, uint32 stateSeq,
|
||||
const void* buffer, uint64 pos,
|
||||
uint32 len);
|
||||
status_t ReleaseLockOwner(OpenFileCookie* cookie,
|
||||
status_t ReleaseLockOwner(OpenState* state,
|
||||
LockOwner* owner);
|
||||
|
||||
RPC::Call* Request();
|
||||
@@ -86,8 +87,7 @@ private:
|
||||
void _InitHeader();
|
||||
|
||||
void _GenerateLockOwner(XDR::WriteStream& stream,
|
||||
OpenFileCookie* cookie,
|
||||
LockOwner* owner);
|
||||
OpenState* state, LockOwner* owner);
|
||||
status_t _GenerateClientId(XDR::WriteStream& stream,
|
||||
const RPC::Server* server);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user