Merge branch 'nfs4'

This commit is contained in:
Pawel Dziepak 2013-04-09 03:15:11 +02:00
commit 6f840fdf69
12 changed files with 186 additions and 107 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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();
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();
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))
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();
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();
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)

View File

@ -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,18 +36,43 @@ 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:
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
case NFS4ERR_LOCKED:
@ -48,9 +81,10 @@ 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();
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;

View File

@ -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,

View File

@ -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();
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();
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,6 +306,8 @@ OpenState::Close()
ReplyInterpreter& reply = request.Reply();
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
@ -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);
}

View File

@ -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();

View File

@ -27,7 +27,7 @@ void
VnodeToInode::Replace(Inode* newInode)
{
WriteLocker _(fLock);
if (fInode != NULL && !IsRoot())
if (!IsRoot())
delete fInode;
fInode = newInode;

View File

@ -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);
}