[haiku-commits] BRANCH pdziepak-github.nfs4 - src/add-ons/kernel/file_systems/nfs4

  • From: pdziepak-github.nfs4 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 9 Apr 2013 02:15:31 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/pdziepak-github/nfs4'
old head: 46bffd5839fc9a1cc8a2277ca5dea4664d082ec9
new head: fa1ca5e20c4aefee918ed52799fb2c99fbe846e3
overview: https://github.com/pdziepak/Haiku/compare/46bffd5...fa1ca5e

----------------------------------------------------------------------------

fa1ca5e: nfs4: use exponential backoff when the server ask to wait

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      fa1ca5e20c4aefee918ed52799fb2c99fbe846e3
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Mon Apr  8 23:55:23 2013 UTC

----------------------------------------------------------------------------

9 files changed, 149 insertions(+), 73 deletions(-)
.../kernel/file_systems/nfs4/Delegation.cpp      |   5 +-
src/add-ons/kernel/file_systems/nfs4/Inode.cpp   |   3 +-
.../kernel/file_systems/nfs4/InodeDir.cpp        |   3 +-
src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h  |   8 ++
.../kernel/file_systems/nfs4/NFS4Inode.cpp       | 113 +++++++++++--------
.../kernel/file_systems/nfs4/NFS4Object.cpp      |  62 +++++++---
.../kernel/file_systems/nfs4/NFS4Object.h        |   4 +-
.../kernel/file_systems/nfs4/OpenState.cpp       |  15 ++-
.../kernel/file_systems/nfs4/RootInode.cpp       |   9 +-

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp
index 2fce4fd..086a2a4 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp
@@ -40,6 +40,7 @@ Delegation::GiveUp(bool truncate)
 status_t
 Delegation::ReturnDelegation()
 {
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -54,8 +55,10 @@ Delegation::ReturnDelegation()
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv, NULL, 
fInode->GetOpenState()))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL,
+                               fInode->GetOpenState())) {
                        continue;
+               }
 
                reply.PutFH();
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
index 6afceaa..e14598c 100644
--- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp
@@ -60,6 +60,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo& fi, 
Inode** _inode)
        inode->fInfo = fi;
        inode->fFileSystem = fs;
 
+       uint32 attempt = 0;
        uint64 size;
        do {
                RPC::Server* serv = fs->Server();
@@ -78,7 +79,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo& fi, 
Inode** _inode)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (inode->HandleErrors(reply.NFS4Error(), serv))
+               if (inode->HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp 
b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
index 0ea69d0..eef37a6 100644
--- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp
@@ -146,6 +146,7 @@ Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
 {
        ASSERT(de != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -166,7 +167,7 @@ Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h 
b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h
index aab14e6..d0d2514 100644
--- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h
+++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h
@@ -367,5 +367,13 @@ sSecToBigTime(uint32 sec)
 }
 
 
+static inline bool
+IsFileHandleInvalid(uint32 error)
+{
+       return error == NFS4ERR_BADHANDLE || error == NFS4ERR_FHEXPIRED
+               || error == NFS4ERR_STALE;
+}
+
+
 #endif // NFS4DEFS_H
 
diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp
index a351979..d723502 100644
--- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp
@@ -20,6 +20,7 @@ NFS4Inode::GetChangeInfo(uint64* change, bool attrDir)
 {
        ASSERT(change != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -39,7 +40,7 @@ NFS4Inode::GetChangeInfo(uint64* change, bool attrDir)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -62,6 +63,7 @@ NFS4Inode::GetChangeInfo(uint64* change, bool attrDir)
 status_t
 NFS4Inode::CommitWrites()
 {
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -76,7 +78,7 @@ NFS4Inode::CommitWrites()
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -90,6 +92,7 @@ NFS4Inode::Access(uint32* allowed)
 {
        ASSERT(allowed != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -104,7 +107,7 @@ NFS4Inode::Access(uint32* allowed)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -120,6 +123,7 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* 
fileID,
 {
        ASSERT(name != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -150,7 +154,7 @@ NFS4Inode::LookUp(const char* name, uint64* change, uint64* 
fileID,
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -209,6 +213,7 @@ NFS4Inode::Link(Inode* dir, const char* name, ChangeInfo* 
changeInfo)
        ASSERT(name != NULL);
        ASSERT(changeInfo != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -225,7 +230,7 @@ NFS4Inode::Link(Inode* dir, const char* name, ChangeInfo* 
changeInfo)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -244,6 +249,7 @@ NFS4Inode::ReadLink(void* buffer, size_t* length)
        ASSERT(buffer != NULL);
        ASSERT(length != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -258,7 +264,7 @@ NFS4Inode::ReadLink(void* buffer, size_t* length)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -278,6 +284,7 @@ NFS4Inode::GetStat(AttrValue** values, uint32* count, 
OpenAttrCookie* cookie)
        ASSERT(values != NULL);
        ASSERT(count != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -300,7 +307,7 @@ NFS4Inode::GetStat(AttrValue** values, uint32* count, 
OpenAttrCookie* cookie)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -315,6 +322,7 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, 
uint32 attrCount)
 {
        ASSERT(attrs != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -334,7 +342,7 @@ NFS4Inode::WriteStat(OpenState* state, AttrValue* attrs, 
uint32 attrCount)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -360,9 +368,10 @@ NFS4Inode::RenameNode(Inode* from, Inode* to, const char* 
fromName,
        ASSERT(fromChange != NULL);
        ASSERT(toChange != NULL);
 
+       uint32 attempt = 0;
        do {
-               RPC::Server* serv = from->fFileSystem->Server();
-               Request request(serv, from->fFileSystem);
+               RPC::Server* server = from->fFileSystem->Server();
+               Request request(server, from->fFileSystem);
                RequestBuilder& req = request.Builder();
 
                if (attribute)
@@ -388,24 +397,14 @@ NFS4Inode::RenameNode(Inode* from, Inode* to, const char* 
fromName,
 
                ReplyInterpreter& reply = request.Reply();
 
-               // FileHandle has expired
-               if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
-                       from->fInfo.UpdateFileHandles(from->fFileSystem);
-                       to->fInfo.UpdateFileHandles(to->fFileSystem);
+               // If we have to wait, migrate to another server, etc then the 
first
+               // HandleErrors() will do that. However, if the file handles
+               // were invalid then we need to update both Inodes.
+               bool retry = from->HandleErrors(attempt, reply.NFS4Error(), 
server);
+               if (IsFileHandleInvalid(reply.NFS4Error()))
+                       retry |= to->HandleErrors(attempt, reply.NFS4Error(), 
server);
+               if (retry)
                        continue;
-               }
-
-               // filesystem has been moved
-               if (reply.NFS4Error() == NFS4ERR_MOVED) {
-                       from->fFileSystem->Migrate(serv);
-                       continue;
-               }
-
-               // need to wait
-               if (reply.NFS4Error() == NFS4ERR_DELAY) {
-                       snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE, 
B_RELATIVE_TIMEOUT);
-                       continue;
-               }
 
                reply.PutFH();
                reply.SaveFH();
@@ -455,6 +454,7 @@ NFS4Inode::CreateFile(const char* name, int mode, int 
perms, OpenState* state,
        bool confirm;
        status_t result;
 
+       uint32 attempt = 0;
        uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
        do {
                state->fClientID = fFileSystem->NFSServer()->ClientId();
@@ -499,8 +499,10 @@ NFS4Inode::CreateFile(const char* name, int mode, int 
perms, OpenState* state,
 
                sequence += IncrementSequence(reply.NFS4Error());
 
-               if (HandleErrors(reply.NFS4Error(), serv, NULL, state, 
&sequence))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, state,
+                               &sequence)) {
                        continue;
+               }
 
                reply.PutFH();
 
@@ -549,6 +551,8 @@ NFS4Inode::OpenFile(OpenState* state, int mode, 
OpenDelegationData* delegation)
 
        bool confirm;
        status_t result;
+
+       uint32 attempt = 0;
        uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
        do {
                state->fClientID = fFileSystem->NFSServer()->ClientId();
@@ -594,8 +598,10 @@ NFS4Inode::OpenFile(OpenState* state, int mode, 
OpenDelegationData* delegation)
 
                sequence += IncrementSequence(reply.NFS4Error());
 
-               if (HandleErrors(reply.NFS4Error(), serv, NULL, state, 
&sequence))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, state,
+                               &sequence)) {
                        continue;
+               }
 
                // Verify if the file we want to open is the file this Inode
                // represents.
@@ -656,6 +662,8 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, int 
mode,
 
        bool confirm;
        status_t result;
+
+       uint32 attempt = 0;
        uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
        do {
                state->fClientID = fFileSystem->NFSServer()->ClientId();
@@ -680,8 +688,10 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, 
int mode,
 
                sequence += IncrementSequence(reply.NFS4Error());
 
-               if (HandleErrors(reply.NFS4Error(), serv, NULL, state, 
&sequence))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, state,
+                               &sequence)) {
                        continue;
+               }
 
                reply.PutFH();
                result = reply.Open(state->fStateID, &state->fStateSeq, 
&confirm,
@@ -716,6 +726,7 @@ NFS4Inode::ReadFile(OpenStateCookie* cookie, OpenState* 
state, uint64 position,
        ASSERT(buffer != NULL);
        ASSERT(eof != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -730,7 +741,7 @@ NFS4Inode::ReadFile(OpenStateCookie* cookie, OpenState* 
state, uint64 position,
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv, cookie, state))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, cookie, 
state))
                        continue;
 
                reply.PutFH();
@@ -751,6 +762,7 @@ NFS4Inode::WriteFile(OpenStateCookie* cookie, OpenState* 
state, uint64 position,
        ASSERT(length != NULL);
        ASSERT(buffer != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -767,7 +779,7 @@ NFS4Inode::WriteFile(OpenStateCookie* cookie, OpenState* 
state, uint64 position,
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv, cookie, state))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, cookie, 
state))
                        continue;
 
                reply.PutFH();
@@ -790,6 +802,7 @@ NFS4Inode::CreateObject(const char* name, const char* path, 
int mode,
        ASSERT(changeInfo != NULL);
        ASSERT(handle != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -829,7 +842,7 @@ NFS4Inode::CreateObject(const char* name, const char* path, 
int mode,
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -869,6 +882,7 @@ NFS4Inode::RemoveObject(const char* name, FileType type, 
ChangeInfo* changeInfo,
        ASSERT(name != NULL);
        ASSERT(changeInfo != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -899,7 +913,7 @@ NFS4Inode::RemoveObject(const char* name, FileType type, 
ChangeInfo* changeInfo,
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -949,6 +963,7 @@ NFS4Inode::ReadDirOnce(DirEntry** dirents, uint32* count, 
OpenDirCookie* cookie,
        ASSERT(count != NULL);
        ASSERT(eof != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -975,7 +990,7 @@ NFS4Inode::ReadDirOnce(DirEntry** dirents, uint32* count, 
OpenDirCookie* cookie,
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -1022,6 +1037,7 @@ NFS4Inode::OpenAttrDir(FileHandle* handle)
 {
        ASSERT(handle != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -1037,7 +1053,7 @@ NFS4Inode::OpenAttrDir(FileHandle* handle)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), serv))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv))
                        continue;
 
                reply.PutFH();
@@ -1059,6 +1075,7 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* 
type, uint64* position,
        ASSERT(position != NULL);
        ASSERT(length != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -1072,8 +1089,10 @@ NFS4Inode::TestLock(OpenFileCookie* cookie, LockType* 
type, uint64* position,
                        return result;
 
                ReplyInterpreter& reply = request.Reply();
-               if (HandleErrors(reply.NFS4Error(), serv, cookie))
-                       continue;
+               if (reply.NFS4Error() != NFS4ERR_DENIED) {
+                       if (HandleErrors(attempt, reply.NFS4Error(), serv, 
cookie))
+                               continue;
+               }
 
                reply.PutFH();
                result = reply.LockT(position, length, type);
@@ -1096,6 +1115,7 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* 
lockInfo, bool wait)
        ASSERT(cookie != NULL);
        ASSERT(lockInfo != NULL);
 
+       uint32 attempt = 0;
        uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
        do {
                MutexLocker ownerLocker(lockInfo->fOwner->fLock);
@@ -1121,15 +1141,13 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, 
LockInfo* lockInfo, bool wait)
                result = reply.Lock(lockInfo);
 
                ownerLocker.Unlock();
-               if (wait && reply.NFS4Error() == NFS4ERR_DENIED) {
-                       fFileSystem->OpenOwnerSequenceUnlock(sequence);
-                       snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE,
-                               B_RELATIVE_TIMEOUT);
-                       sequence = fFileSystem->OpenOwnerSequenceLock();
-                       continue;
+
+               if (reply.NFS4Error() != NFS4ERR_DENIED || wait) {
+                       if (HandleErrors(attempt, reply.NFS4Error(), serv, 
cookie, NULL,
+                                       &sequence)) {
+                               continue;
+                       }
                }
-               if (HandleErrors(reply.NFS4Error(), serv, cookie, NULL, 
&sequence))
-                       continue;
 
                fFileSystem->OpenOwnerSequenceUnlock(sequence);
                if (result != B_OK)
@@ -1146,6 +1164,7 @@ NFS4Inode::ReleaseLock(OpenFileCookie* cookie, LockInfo* 
lockInfo)
        ASSERT(cookie != NULL);
        ASSERT(lockInfo != NULL);
 
+       uint32 attempt = 0;
        do {
                MutexLocker ownerLocker(lockInfo->fOwner->fLock);
 
@@ -1166,7 +1185,7 @@ NFS4Inode::ReleaseLock(OpenFileCookie* cookie, LockInfo* 
lockInfo)
                result = reply.LockU(lockInfo);
 
                ownerLocker.Unlock();
-               if (HandleErrors(reply.NFS4Error(), serv, cookie))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, cookie))
                        continue;
 
                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 6938193..5211a4d 100644
--- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp
@@ -14,12 +14,20 @@
 #include "Request.h"
 
 
+static inline bigtime_t
+RetryDelay(uint32 attempt, uint32 leaseTime = 0)
+{
+       bigtime_t delay = (1 << attempt - 1) * 100000;
+       if (leaseTime != 0)
+               delay = min_c(delay, sSecToBigTime(leaseTime));
+       return delay;
+}
+
+
 bool
-NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
+NFS4Object::HandleErrors(uint32& attempt, uint32 nfs4Error, RPC::Server* 
server,
        OpenStateCookie* cookie, OpenState* state, uint32* sequence)
 {
-       uint32 leaseTime;
-
        // No request send by the client should cause any of the following 
errors.
        ASSERT(nfs4Error != NFS4ERR_CLID_INUSE);
        ASSERT(nfs4Error != NFS4ERR_NOFILEHANDLE);
@@ -28,17 +36,42 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* 
serv,
        ASSERT(nfs4Error != NFS4ERR_LOCKS_HELD);
        ASSERT(nfs4Error != NFS4ERR_OP_ILLEGAL);
 
+       attempt++;
+
        if (cookie != NULL)
                state = cookie->fOpenState;
 
+       uint32 leaseTime;
+       status_t result;
        switch (nfs4Error) {
                case NFS4_OK:
                        return false;
 
                // retransmission of CLOSE caused seqid to fall back
                case NFS4ERR_BAD_SEQID:
-                       ASSERT(sequence != NULL);
-                       (*sequence)++;
+                       if (attempt == 1) {
+                               ASSERT(sequence != NULL);
+                               (*sequence)++;
+                               return true;
+                       }
+                       return false;
+
+               // resource is locked, we need to wait
+               case NFS4ERR_DENIED:
+                       if (sequence != NULL)
+                               fFileSystem->OpenOwnerSequenceUnlock(*sequence);
+
+                       result = acquire_sem_etc(cookie->fSnoozeCancel, 1,
+                               B_RELATIVE_TIMEOUT, RetryDelay(attempt));
+
+                       if (sequence != NULL)
+                               *sequence = 
fFileSystem->OpenOwnerSequenceLock();
+
+                       if (result != B_TIMED_OUT) {
+                               if (result == B_OK)
+                                       release_sem(cookie->fSnoozeCancel);
+                               return false;
+                       }
                        return true;
 
                // server needs more time, we need to wait
@@ -48,8 +81,9 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
                                fFileSystem->OpenOwnerSequenceUnlock(*sequence);
 
                        if (cookie == NULL) {
-                               snooze_etc(sSecToBigTime(5), B_SYSTEM_TIMEBASE,
+                               snooze_etc(RetryDelay(attempt), 
B_SYSTEM_TIMEBASE,
                                        B_RELATIVE_TIMEOUT);
+                               
 
                                if (sequence != NULL)
                                        *sequence = 
fFileSystem->OpenOwnerSequenceLock();
@@ -58,8 +92,8 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
                        }
 
                        if ((cookie->fMode & O_NONBLOCK) == 0) {
-                               status_t result = 
acquire_sem_etc(cookie->fSnoozeCancel, 1,
-                                       B_RELATIVE_TIMEOUT, sSecToBigTime(5));
+                               result = acquire_sem_etc(cookie->fSnoozeCancel, 
1,
+                                       B_RELATIVE_TIMEOUT, 
RetryDelay(attempt));
 
                                if (sequence != NULL)
                                        *sequence = 
fFileSystem->OpenOwnerSequenceLock();
@@ -83,7 +117,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
                                fFileSystem->OpenOwnerSequenceUnlock(*sequence);
 
                        if (cookie == NULL) {
-                               snooze_etc(sSecToBigTime(leaseTime) / 3, 
B_SYSTEM_TIMEBASE,
+                               snooze_etc(RetryDelay(attempt, leaseTime), 
B_SYSTEM_TIMEBASE,
                                        B_RELATIVE_TIMEOUT);
                                if (sequence != NULL)
                                        *sequence = 
fFileSystem->OpenOwnerSequenceLock();
@@ -91,8 +125,8 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
                        }
 
                        if ((cookie->fMode & O_NONBLOCK) == 0) {
-                               status_t result = 
acquire_sem_etc(cookie->fSnoozeCancel, 1,
-                                       B_RELATIVE_TIMEOUT, 
sSecToBigTime(leaseTime) / 3);
+                               result = acquire_sem_etc(cookie->fSnoozeCancel, 
1,
+                                       B_RELATIVE_TIMEOUT, RetryDelay(attempt, 
leaseTime));
 
                                if (sequence != NULL)
                                        *sequence = 
fFileSystem->OpenOwnerSequenceLock();
@@ -125,7 +159,6 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* 
serv,
                        return false;
 
                // File Handle has expired, is invalid or the node has been 
deleted
-               case NFS4ERR_NOFILEHANDLE:
                case NFS4ERR_BADHANDLE:
                case NFS4ERR_FHEXPIRED:
                case NFS4ERR_STALE:
@@ -136,7 +169,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* 
serv,
                // filesystem has been moved
                case NFS4ERR_LEASE_MOVED:
                case NFS4ERR_MOVED:
-                       fFileSystem->Migrate(serv);
+                       fFileSystem->Migrate(server);
                        return true;
 
                // lease has expired
@@ -160,6 +193,7 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* 
state,
        ASSERT(state != NULL);
        ASSERT(sequence != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* serv = fFileSystem->Server();
                Request request(serv, fFileSystem);
@@ -177,7 +211,7 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* 
state,
 
                *sequence += IncrementSequence(reply.NFS4Error());
 
-               if (HandleErrors(reply.NFS4Error(), serv, NULL, state))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, state))
                        continue;
 
                reply.PutFH();
diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h 
b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h
index d0ac9cb..2ec041e 100644
--- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h
+++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h
@@ -18,8 +18,8 @@ class OpenState;
 
 class NFS4Object {
 public:
-                       bool            HandleErrors(uint32 nfs4Error, 
RPC::Server* serv,
-                                                       OpenStateCookie* cookie 
= NULL,
+                       bool            HandleErrors(uint32& attempt, uint32 
nfs4Error,
+                                                       RPC::Server* server, 
OpenStateCookie* cookie = NULL,
                                                        OpenState* state = 
NULL, uint32* sequence = NULL);
 
                        status_t        ConfirmOpen(const FileHandle& 
fileHandle,
diff --git a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp 
b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp
index 21ac8d5..e5935de 100644
--- a/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/OpenState.cpp
@@ -114,6 +114,7 @@ OpenState::_ReleaseLockOwner(LockOwner* owner)
 {
        ASSERT(owner != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* server = fFileSystem->Server();
                Request request(server, fFileSystem);
@@ -127,7 +128,7 @@ OpenState::_ReleaseLockOwner(LockOwner* owner)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), server))
+               if (HandleErrors(attempt, reply.NFS4Error(), server))
                        continue;
 
                return reply.ReleaseLockOwner();
@@ -166,6 +167,7 @@ OpenState::_ReclaimOpen(uint64 newClientID)
        uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
        OpenDelegation delegType = fDelegation != NULL ? fDelegation->Type()
                : OPEN_DELEGATE_NONE;
+       uint32 attempt = 0;
        do {
                RPC::Server* server = fFileSystem->Server();
                Request request(server, fFileSystem);
@@ -187,7 +189,8 @@ OpenState::_ReclaimOpen(uint64 newClientID)
                sequence += IncrementSequence(reply.NFS4Error());
 
                if (reply.NFS4Error() != NFS4ERR_STALE_CLIENTID
-                       && HandleErrors(reply.NFS4Error(), server, NULL, NULL, 
&sequence)) {
+                       && HandleErrors(attempt, reply.NFS4Error(), server, 
NULL, NULL,
+                               &sequence)) {
                        continue;
                }
 
@@ -233,6 +236,7 @@ OpenState::_ReclaimLocks(uint64 newClientID)
                        linfo->fOwner->fClientId = newClientID;
                }
 
+               uint32 attempt = 0;
                uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
                do {
                        RPC::Server* server = fFileSystem->Server();
@@ -254,7 +258,7 @@ OpenState::_ReclaimLocks(uint64 newClientID)
 
                        if (reply.NFS4Error() != NFS4ERR_STALE_CLIENTID
                                && reply.NFS4Error() !=  NFS4ERR_STALE_STATEID
-                               && HandleErrors(reply.NFS4Error(), server, 
NULL, NULL,
+                               && HandleErrors(attempt, reply.NFS4Error(), 
server, NULL, NULL,
                                        &sequence)) {
                                continue;
                        }
@@ -283,6 +287,7 @@ OpenState::Close()
        MutexLocker _(fLock);
        fOpened = false;
 
+       uint32 attempt = 0;
        uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
        do {
                RPC::Server* serv = fFileSystem->Server();
@@ -310,8 +315,10 @@ OpenState::Close()
                        return B_OK;
                }
 
-               if (HandleErrors(reply.NFS4Error(), serv, NULL, this, 
&sequence))
+               if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, this,
+                               &sequence)) {
                        continue;
+               }
                fFileSystem->OpenOwnerSequenceUnlock(sequence);
 
                reply.PutFH();
diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp 
b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp
index e79f832..ed9dee0 100644
--- a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp
+++ b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp
@@ -58,6 +58,7 @@ RootInode::_UpdateInfo(bool force)
        if (fInfoCacheExpire > time(NULL))
                return B_OK;
 
+       uint32 attempt = 0;
        do {
                RPC::Server* server = fFileSystem->Server();
                Request request(server, fFileSystem);
@@ -75,7 +76,7 @@ RootInode::_UpdateInfo(bool force)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), server))
+               if (HandleErrors(attempt, reply.NFS4Error(), server))
                        continue;
 
                reply.PutFH();
@@ -146,6 +147,7 @@ RootInode::_UpdateInfo(bool force)
 bool
 RootInode::ProbeMigration()
 {
+       uint32 attempt = 0;
        do {
                RPC::Server* server = fFileSystem->Server();
                Request request(server, fFileSystem);
@@ -163,7 +165,7 @@ RootInode::ProbeMigration()
                if (reply.NFS4Error() == NFS4ERR_MOVED)
                        return true;
 
-               if (HandleErrors(reply.NFS4Error(), server))
+               if (HandleErrors(attempt, reply.NFS4Error(), server))
                        continue;
 
                return false;
@@ -176,6 +178,7 @@ RootInode::GetLocations(AttrValue** attrv)
 {
        ASSERT(attrv != NULL);
 
+       uint32 attempt = 0;
        do {
                RPC::Server* server = fFileSystem->Server();
                Request request(server, fFileSystem);
@@ -191,7 +194,7 @@ RootInode::GetLocations(AttrValue** attrv)
 
                ReplyInterpreter& reply = request.Reply();
 
-               if (HandleErrors(reply.NFS4Error(), server))
+               if (HandleErrors(attempt, reply.NFS4Error(), server))
                        continue;
 
                reply.PutFH();


Other related posts: