nfs4: use exponential backoff when the server ask to wait
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user