diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp index 2fce4fde6c..086a2a4655 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/FileInfo.cpp b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp index d620481c77..45f002d202 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp @@ -148,8 +148,12 @@ FileInfo::UpdateFileHandles(FileSystem* fs) uint32 i; InodeNames* names = fNames; - for (i = 0; names != NULL; i++) + for (i = 0; names != NULL; i++) { + if (names->fNames.IsEmpty()) + return B_ENTRY_NOT_FOUND; + names = names->fNames.Head()->fParent; + } if (i > 0) { names = fNames; diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 6afceaafc1..e14598c9a4 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 0ea69d0685..eef37a619a 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 aab14e6596..d0d25142b4 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 a3519792ef..af9b47d07d 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(); @@ -497,12 +497,14 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, OpenState* state, ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + 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, delegation, changeInfo); @@ -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(); @@ -592,11 +596,6 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); - - if (HandleErrors(reply.NFS4Error(), serv, NULL, state, &sequence)) - continue; - // Verify if the file we want to open is the file this Inode // represents. if (fFileSystem->IsAttrSupported(FATTR4_FILEID) @@ -609,16 +608,21 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) } result = reply.Verify(); - if (result != B_OK) + if (result != B_OK && reply.NFS4Error() == NFS4ERR_NOT_SAME) { fFileSystem->OpenOwnerSequenceUnlock(sequence); - - if (result != B_OK && reply.NFS4Error() == NFS4ERR_NOT_SAME) return B_ENTRY_NOT_FOUND; - else if (result != B_OK) - return result; + } + } + + result = reply.PutFH(); + if (result == B_OK) + sequence += IncrementSequence(reply.NFS4Error()); + + if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, state, + &sequence)) { + continue; } - reply.PutFH(); result = reply.Open(state->fStateID, &state->fStateSeq, &confirm, delegation); if (result != B_OK) { @@ -656,6 +660,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(); @@ -678,12 +684,15 @@ NFS4Inode::OpenAttr(OpenState* state, const char* name, int mode, ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + 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, delegation); @@ -716,6 +725,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 +740,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 +761,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 +778,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 +801,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 +841,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 +881,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 +912,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 +962,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 +989,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 +1036,7 @@ NFS4Inode::OpenAttrDir(FileHandle* handle) { ASSERT(handle != NULL); + uint32 attempt = 0; do { RPC::Server* serv = fFileSystem->Server(); Request request(serv, fFileSystem); @@ -1037,7 +1052,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 +1074,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 +1088,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 +1114,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); @@ -1115,21 +1134,20 @@ NFS4Inode::AcquireLock(OpenFileCookie* cookie, LockInfo* lockInfo, bool wait) ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + sequence += IncrementSequence(reply.NFS4Error()); - reply.PutFH(); 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 69381930f9..e98abe4182 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); @@ -175,12 +209,13 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state, ReplyInterpreter& reply = request.Reply(); - *sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + *sequence += IncrementSequence(reply.NFS4Error()); - if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) + if (HandleErrors(attempt, reply.NFS4Error(), serv, NULL, state)) continue; - reply.PutFH(); result = reply.OpenConfirm(&state->fStateSeq); if (result != B_OK) return result; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.h index d0ac9cb83a..2ec041e20a 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 21ac8d5b78..73df95155a 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); @@ -184,15 +186,16 @@ OpenState::_ReclaimOpen(uint64 newClientID) ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + 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; } - reply.PutFH(); - result = reply.Open(fStateID, &fStateSeq, &confirm, &delegation); if (result != B_OK) { fFileSystem->OpenOwnerSequenceUnlock(sequence); @@ -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(); @@ -250,16 +254,17 @@ OpenState::_ReclaimLocks(uint64 newClientID) ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + sequence += IncrementSequence(reply.NFS4Error()); 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; } - reply.PutFH(); reply.Lock(linfo); fFileSystem->OpenOwnerSequenceUnlock(sequence); @@ -283,6 +288,7 @@ OpenState::Close() MutexLocker _(fLock); fOpened = false; + uint32 attempt = 0; uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); do { RPC::Server* serv = fFileSystem->Server(); @@ -300,7 +306,9 @@ OpenState::Close() ReplyInterpreter& reply = request.Reply(); - sequence += IncrementSequence(reply.NFS4Error()); + result = reply.PutFH(); + if (result == B_OK) + sequence += IncrementSequence(reply.NFS4Error()); // RFC 3530 8.10.1. Some servers does not do anything to help client // recognize retried CLOSE requests so we just assume that BAD_STATEID @@ -310,12 +318,12 @@ 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(); - return reply.Close(); } while (true); } diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp index e79f832823..ed9dee0615 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(); diff --git a/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.cpp b/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.cpp index 2e20cfc22b..6e260bc4ba 100644 --- a/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.cpp @@ -27,7 +27,7 @@ void VnodeToInode::Replace(Inode* newInode) { WriteLocker _(fLock); - if (fInode != NULL && !IsRoot()) + if (!IsRoot()) delete fInode; fInode = newInode; diff --git a/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.h b/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.h index b75528aaea..ee04a454c3 100644 --- a/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.h +++ b/src/add-ons/kernel/file_systems/nfs4/VnodeToInode.h @@ -72,7 +72,7 @@ VnodeToInode::VnodeToInode(ino_t id, FileSystem* fileSystem) inline VnodeToInode::~VnodeToInode() { - Replace(NULL); + Clear(); if (fFileSystem != NULL && !IsRoot()) fFileSystem->InoIdMap()->RemoveEntry(fID); rw_lock_destroy(&fLock); @@ -96,10 +96,7 @@ VnodeToInode::Unlock() inline void VnodeToInode::Clear() { - WriteLocker _(fLock); - if (!IsRoot()) - delete fInode; - fInode = NULL; + Replace(NULL); }