Merge branch 'nfs4'
This commit is contained in:
commit
6f840fdf69
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -27,7 +27,7 @@ void
|
||||
VnodeToInode::Replace(Inode* newInode)
|
||||
{
|
||||
WriteLocker _(fLock);
|
||||
if (fInode != NULL && !IsRoot())
|
||||
if (!IsRoot())
|
||||
delete fInode;
|
||||
|
||||
fInode = newInode;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user