From bfa20379a3d5756dda6f3ebab0dcf52b6f4ca749 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Mon, 6 Aug 2012 03:18:46 +0200 Subject: [PATCH] nfs4: Reclaim delegations after server reboot --- .../kernel/file_systems/nfs4/Cookie.cpp | 92 ++-------- src/add-ons/kernel/file_systems/nfs4/Cookie.h | 21 +-- .../kernel/file_systems/nfs4/Delegation.h | 15 +- .../kernel/file_systems/nfs4/FileSystem.cpp | 29 ++-- .../kernel/file_systems/nfs4/FileSystem.h | 11 +- .../kernel/file_systems/nfs4/Inode.cpp | 60 +++++-- .../kernel/file_systems/nfs4/InodeRegular.cpp | 14 +- .../kernel/file_systems/nfs4/NFS4Inode.cpp | 4 +- .../kernel/file_systems/nfs4/NFS4Object.cpp | 1 + .../kernel/file_systems/nfs4/NFS4Server.cpp | 56 +----- .../kernel/file_systems/nfs4/NFS4Server.h | 3 - .../kernel/file_systems/nfs4/OpenState.cpp | 160 +++++++++++++++++- .../kernel/file_systems/nfs4/OpenState.h | 22 +++ .../file_systems/nfs4/RequestBuilder.cpp | 25 ++- .../kernel/file_systems/nfs4/RequestBuilder.h | 18 +- 15 files changed, 308 insertions(+), 223 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp index a2970b7a95..23a38e2950 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.h b/src/add-ons/kernel/file_systems/nfs4/Cookie.h index 4af8899333..1fd8c9c29a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.h +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.h @@ -12,9 +12,10 @@ #include #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 { diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.h b/src/add-ons/kernel/file_systems/nfs4/Delegation.h index d54da15a07..27099e2281 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Delegation.h +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp index d5e3d8bf26..9379f3e638 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp @@ -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(); diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h index 7814f8e667..0bd634dd6e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -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 fOpenDelegations; mutex fDelegationLock; AVLTreeMap fHandleToDelegation; - OpenFileCookie* fOpenFiles; + OpenState* fOpenFiles; uint32 fOpenCount; mutex fOpenLock; diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 0f0846e7e8..e56fdc9998 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 920821548b..76e4820af7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index c2208fb8af..e45f08f4f2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -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) { diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index 327c075246..192e691f00 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -10,6 +10,7 @@ #include "Cookie.h" #include "FileSystem.h" #include "NFS4Object.h" +#include "OpenState.h" #include "Request.h" diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 88fbce1041..05c85035f5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -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) { diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index 4d37a960a8..d312018e21 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -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(); diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp index 236ff7c243..388b62fc8e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp @@ -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() { diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.h b/src/add-ons/kernel/file_systems/nfs4/OpenState.h index ecf10a8a41..8cfdce5253 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.h +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.h @@ -13,6 +13,7 @@ #include #include +#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); }; diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 17d825946b..08f4dff29c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -13,6 +13,7 @@ #include #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++; diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index d850c3c176..d958d6d05a 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -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);