added 1 changeset to branch 'refs/remotes/pdziepak-github/nfs4' old head: 0e0d53c7995f23e83364ec628c9623041e2b22bc new head: b1fd656d454ab89fbfdac09fda1b6aafd81bbe89 ---------------------------------------------------------------------------- b1fd656: nfs4: Fix server reboot recovery [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: b1fd656d454ab89fbfdac09fda1b6aafd81bbe89 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Fri Aug 10 00:34:41 2012 UTC ---------------------------------------------------------------------------- 14 files changed, 73 insertions(+), 41 deletions(-) .../kernel/file_systems/nfs4/Delegation.cpp | 2 +- src/add-ons/kernel/file_systems/nfs4/Delegation.h | 8 ++++ .../kernel/file_systems/nfs4/FileSystem.cpp | 22 +++-------- src/add-ons/kernel/file_systems/nfs4/FileSystem.h | 4 +- src/add-ons/kernel/file_systems/nfs4/Inode.cpp | 8 ++-- src/add-ons/kernel/file_systems/nfs4/Inode.h | 9 +++++ .../kernel/file_systems/nfs4/InodeRegular.cpp | 1 - src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp | 2 +- .../kernel/file_systems/nfs4/NFS4Object.cpp | 9 ++++- src/add-ons/kernel/file_systems/nfs4/NFS4Object.h | 3 +- .../kernel/file_systems/nfs4/NFS4Server.cpp | 6 ++- src/add-ons/kernel/file_systems/nfs4/OpenState.cpp | 33 +++++++++++++--- src/add-ons/kernel/file_systems/nfs4/OpenState.h | 6 +-- .../kernel/file_systems/nfs4/ReplyInterpreter.cpp | 1 + ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp index 19ea2f2..a0ce499 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp @@ -53,7 +53,7 @@ Delegation::ReturnDelegation() ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, fInode->GetOpenState())) continue; reply.PutFH(); diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.h b/src/add-ons/kernel/file_systems/nfs4/Delegation.h index f901173..807d526 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Delegation.h +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.h @@ -25,6 +25,7 @@ public: status_t GiveUp(bool truncate = false); + inline void SetData(const OpenDelegationData& data); inline Inode* GetInode(); inline OpenDelegation Type(); @@ -39,6 +40,13 @@ private: }; +inline void +Delegation::SetData(const OpenDelegationData& data) +{ + fData = data; +} + + inline Inode* Delegation::GetInode() { diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp index ecc56b2..d211299 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp @@ -25,7 +25,6 @@ FileSystem::FileSystem() : fNext(NULL), fPrev(NULL), - fOpenFiles(NULL), fOpenCount(0), fOpenOwnerSequence(0), fPath(NULL), @@ -267,7 +266,7 @@ FileSystem::Migrate(const RPC::Server* serv) } -OpenState* +DoublyLinkedList<OpenState>& FileSystem::OpenFilesLock() { mutex_lock(&fOpenLock); @@ -287,11 +286,8 @@ FileSystem::AddOpenFile(OpenState* state) { MutexLocker _(fOpenLock); - state->fPrev = NULL; - state->fNext = fOpenFiles; - if (fOpenFiles != NULL) - fOpenFiles->fPrev = state; - fOpenFiles = state; + fOpenFiles.InsertBefore(fOpenFiles.Head(), state); + NFSServer()->IncUsage(); } @@ -300,13 +296,9 @@ void FileSystem::RemoveOpenFile(OpenState* state) { MutexLocker _(fOpenLock); - if (state == fOpenFiles) - fOpenFiles = state->fNext; - if (state->fNext) - state->fNext->fPrev = state->fPrev; - if (state->fPrev) - state->fPrev->fNext = state->fNext; + fOpenFiles.Remove(state); + NFSServer()->DecUsage(); } @@ -335,8 +327,6 @@ FileSystem::AddDelegation(Delegation* delegation) fHandleToDelegation.Remove(delegation->fInfo.fHandle); fHandleToDelegation.Insert(delegation->fInfo.fHandle, delegation); - - NFSServer()->IncUsage(); } @@ -347,8 +337,6 @@ FileSystem::RemoveDelegation(Delegation* delegation) fDelegationList.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 adfea0a..b055e3b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -30,7 +30,7 @@ public: status_t Migrate(const RPC::Server* serv); - OpenState* OpenFilesLock(); + DoublyLinkedList<OpenState>& OpenFilesLock(); void OpenFilesUnlock(); inline uint32 OpenFilesCount(); void AddOpenFile(OpenState* state); @@ -73,7 +73,7 @@ private: DoublyLinkedList<Delegation> fDelegationList; AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation; - OpenState* fOpenFiles; + DoublyLinkedList<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 cd7f14b..02ea63e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -857,9 +857,9 @@ Inode::RecallReadDelegation() void Inode::ReturnDelegation(bool truncate) { - fMetaCache.UnlockValid(); - fDelegation->GiveUp(truncate); + + fMetaCache.UnlockValid(); fFileSystem->RemoveDelegation(fDelegation); MutexLocker stateLocker(fStateLock); @@ -874,10 +874,8 @@ Inode::ReturnDelegation(bool truncate) void Inode::ReleaseOpenState() { - if (fOpenState->ReleaseReference() == 1) { - fFileSystem->RemoveOpenFile(fOpenState); + if (fOpenState->ReleaseReference() == 1) fOpenState = NULL; - } } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index e5a477a..ab8feec 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -37,6 +37,8 @@ public: inline uint64 Change(); inline bool Dirty(); + inline OpenState* GetOpenState(); + void SetDelegation(Delegation* delegation); void RecallDelegation(bool truncate = false); void RecallReadDelegation(); @@ -230,5 +232,12 @@ Inode::Dirty() } +inline OpenState* +Inode::GetOpenState() +{ + return fOpenState; +} + + #endif // INODE_H diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 2eb1a1b..5490ee0 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -252,7 +252,6 @@ Inode::CloseAttr(OpenAttrCookie* cookie) fFileSystem->RemoveDelegation(cookie->fOpenState->fDelegation); delete cookie->fOpenState->fDelegation; delete cookie->fOpenState; - 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 565b502..4f4dc73 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -553,7 +553,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, state, &sequence)) continue; fFileSystem->OpenOwnerSequenceUnlock(); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index 6663cc3..fc5aecf 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -16,7 +16,7 @@ bool NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, - OpenStateCookie* cookie, OpenState* state) + OpenStateCookie* cookie, OpenState* state, uint32* sequence) { uint32 leaseTime; @@ -67,7 +67,14 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, case NFS4ERR_STALE_CLIENTID: case NFS4ERR_STALE_STATEID: if (state != NULL) { + if (sequence != NULL) + fFileSystem->OpenOwnerSequenceUnlock(false); + fFileSystem->NFSServer()->ServerRebooted(state->fClientID); +dprintf("returned rebooted\n"); + if (sequence != NULL) + *sequence = fFileSystem->OpenOwnerSequenceLock(); +dprintf("locked again\n"); return true; } return false; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h index 3af5129..817b1c2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h @@ -19,7 +19,8 @@ class OpenState; class NFS4Object { public: bool HandleErrors(uint32 nfs4Error, RPC::Server* serv, - OpenStateCookie* cookie = NULL, OpenState* state = NULL); + OpenStateCookie* cookie = NULL, OpenState* state = NULL, + uint32* sequence = NULL); status_t ConfirmOpen(const FileHandle& fileHandle, OpenState* state); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 07acb75..173e527 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -58,11 +58,13 @@ NFS4Server::ServerRebooted(uint64 clientId) MutexLocker _(fFSLock); FileSystem* fs = fFileSystems; while (fs != NULL) { - OpenState* current = fs->OpenFilesLock(); + DoublyLinkedList<OpenState>::Iterator iterator + = fs->OpenFilesLock().GetIterator(); + OpenState* current = iterator.Next(); while (current != NULL) { current->Reclaim(fClientId); - current = current->fNext; + current = iterator.Next(); } fs->OpenFilesUnlock(); diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp index 388b62f..62c93bb 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp @@ -13,6 +13,7 @@ #include "FileSystem.h" #include "Request.h" +#include "WorkQueue.h" OpenState::OpenState() @@ -31,7 +32,9 @@ OpenState::OpenState() OpenState::~OpenState() { + fFileSystem->RemoveOpenFile(this); Close(); + mutex_destroy(&fLock); mutex_destroy(&fLocksLock); @@ -140,9 +143,10 @@ OpenState::Reclaim(uint64 newClientID) if (fClientID == newClientID) return B_OK; fClientID = newClientID; - +dprintf("reclaim start\n"); _ReclaimOpen(newClientID); _ReclaimLocks(newClientID); +dprintf("reclaim end\n"); return B_OK; } @@ -150,10 +154,16 @@ OpenState::Reclaim(uint64 newClientID) status_t OpenState::_ReclaimOpen(uint64 newClientID) { + dprintf("reclaim %s\n", fInfo.fName); + bool confirm; OpenDelegationData delegation; + delegation.fType = OPEN_DELEGATE_NONE; + delegation.fRecall = false; uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); + OpenDelegation delegType = fDelegation != NULL ? fDelegation->Type() + : OPEN_DELEGATE_NONE; do { RPC::Server* server = fFileSystem->Server(); Request request(server); @@ -162,7 +172,7 @@ OpenState::_ReclaimOpen(uint64 newClientID) req.PutFH(fInfo.fHandle); req.Open(CLAIM_PREVIOUS, sequence, sModeToAccess(fMode), newClientID, OPEN4_NOCREATE, fFileSystem->OpenOwner(), NULL, NULL, 0, false, - fDelegation->Type()); + delegType); status_t result = request.Send(); if (result != B_OK) { @@ -172,7 +182,7 @@ OpenState::_ReclaimOpen(uint64 newClientID) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), server)) + if (HandleErrors(reply.NFS4Error(), server, NULL, NULL, &sequence)) continue; fFileSystem->OpenOwnerSequenceUnlock(); @@ -182,10 +192,19 @@ OpenState::_ReclaimOpen(uint64 newClientID) result = reply.Open(fStateID, &fStateSeq, &confirm, &delegation); if (result != B_OK) return result; + + break; } while (true); - if (delegation.fRecall) - fDelegation->GiveUp(); + if (fDelegation != NULL) + fDelegation->SetData(delegation); + + if (delegation.fRecall) { + DelegationRecallArgs* args = new(std::nothrow) DelegationRecallArgs; + args->fDelegation = fDelegation; + args->fTruncate = false; + gWorkQueue->EnqueueJob(DelegationRecall, args); + } if (confirm) return ConfirmOpen(fInfo.fHandle, this); @@ -197,6 +216,8 @@ OpenState::_ReclaimOpen(uint64 newClientID) status_t OpenState::_ReclaimLocks(uint64 newClientID) { + dprintf("reclaim locks %s\n", fInfo.fName); + MutexLocker _(fLocksLock); LockInfo* linfo = fLocks; while (linfo != NULL) { @@ -264,7 +285,7 @@ OpenState::Close() ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv, NULL, this)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, this, &sequence)) continue; fFileSystem->OpenOwnerSequenceUnlock(); diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.h b/src/add-ons/kernel/file_systems/nfs4/OpenState.h index 8cfdce5..f810528 100644 --- a/src/add-ons/kernel/file_systems/nfs4/OpenState.h +++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.h @@ -17,7 +17,8 @@ #include "NFS4Object.h" -struct OpenState : public NFS4Object, public KernelReferenceable { +struct OpenState : public NFS4Object, public KernelReferenceable, + public DoublyLinkedListLinkImpl<OpenState> { OpenState(); ~OpenState(); @@ -38,9 +39,6 @@ struct OpenState : public NFS4Object, public KernelReferenceable { LockOwner* fLockOwners; mutex fOwnerLock; - OpenState* fNext; - OpenState* fPrev; - LockOwner* GetLockOwner(uint32 owner); void AddLock(LockInfo* lock); diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index b26082d..5812827 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -827,6 +827,7 @@ ReplyInterpreter::_NFS4ErrorToHaiku(uint32 x) case NFS4ERR_ISDIR: return B_IS_A_DIRECTORY; case NFS4ERR_INVAL: return B_BAD_VALUE; case NFS4ERR_FBIG: return B_FILE_TOO_LARGE; + case NFS4ERR_NOTSUPP: return B_UNSUPPORTED; // ... case NFS4ERR_DELAY: case NFS4ERR_DENIED: