nfs4: Fix server reboot recovery

This commit is contained in:
Pawel Dziepak
2012-08-10 02:34:41 +02:00
parent 0e0d53c799
commit b1fd656d45
14 changed files with 73 additions and 41 deletions
@@ -53,7 +53,7 @@ Delegation::ReturnDelegation()
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv))
if (HandleErrors(reply.NFS4Error(), serv, NULL, fInode->GetOpenState()))
continue;
reply.PutFH();
@@ -25,6 +25,7 @@ public:
status_t GiveUp(bool truncate = false);
inline void SetData(const OpenDelegationData& data);
inline Inode* GetInode();
inline OpenDelegation Type();
@@ -39,6 +40,13 @@ private:
};
inline void
Delegation::SetData(const OpenDelegationData& data)
{
fData = data;
}
inline Inode*
Delegation::GetInode()
{
@@ -25,7 +25,6 @@ FileSystem::FileSystem()
:
fNext(NULL),
fPrev(NULL),
fOpenFiles(NULL),
fOpenCount(0),
fOpenOwnerSequence(0),
fPath(NULL),
@@ -267,7 +266,7 @@ FileSystem::Migrate(const RPC::Server* serv)
}
OpenState*
DoublyLinkedList<OpenState>&
FileSystem::OpenFilesLock()
{
mutex_lock(&fOpenLock);
@@ -287,11 +286,8 @@ FileSystem::AddOpenFile(OpenState* state)
{
MutexLocker _(fOpenLock);
state->fPrev = NULL;
state->fNext = fOpenFiles;
if (fOpenFiles != NULL)
fOpenFiles->fPrev = state;
fOpenFiles = state;
fOpenFiles.InsertBefore(fOpenFiles.Head(), state);
NFSServer()->IncUsage();
}
@@ -300,13 +296,9 @@ void
FileSystem::RemoveOpenFile(OpenState* state)
{
MutexLocker _(fOpenLock);
if (state == fOpenFiles)
fOpenFiles = state->fNext;
if (state->fNext)
state->fNext->fPrev = state->fPrev;
if (state->fPrev)
state->fPrev->fNext = state->fNext;
fOpenFiles.Remove(state);
NFSServer()->DecUsage();
}
@@ -335,8 +327,6 @@ FileSystem::AddDelegation(Delegation* delegation)
fHandleToDelegation.Remove(delegation->fInfo.fHandle);
fHandleToDelegation.Insert(delegation->fInfo.fHandle, delegation);
NFSServer()->IncUsage();
}
@@ -347,8 +337,6 @@ FileSystem::RemoveDelegation(Delegation* delegation)
fDelegationList.Remove(delegation);
fHandleToDelegation.Remove(delegation->fInfo.fHandle);
NFSServer()->DecUsage();
}
@@ -30,7 +30,7 @@ public:
status_t Migrate(const RPC::Server* serv);
OpenState* OpenFilesLock();
DoublyLinkedList<OpenState>& OpenFilesLock();
void OpenFilesUnlock();
inline uint32 OpenFilesCount();
void AddOpenFile(OpenState* state);
@@ -73,7 +73,7 @@ private:
DoublyLinkedList<Delegation> fDelegationList;
AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation;
OpenState* fOpenFiles;
DoublyLinkedList<OpenState> fOpenFiles;
uint32 fOpenCount;
mutex fOpenLock;
@@ -857,9 +857,9 @@ Inode::RecallReadDelegation()
void
Inode::ReturnDelegation(bool truncate)
{
fMetaCache.UnlockValid();
fDelegation->GiveUp(truncate);
fMetaCache.UnlockValid();
fFileSystem->RemoveDelegation(fDelegation);
MutexLocker stateLocker(fStateLock);
@@ -874,10 +874,8 @@ Inode::ReturnDelegation(bool truncate)
void
Inode::ReleaseOpenState()
{
if (fOpenState->ReleaseReference() == 1) {
fFileSystem->RemoveOpenFile(fOpenState);
if (fOpenState->ReleaseReference() == 1)
fOpenState = NULL;
}
}
@@ -37,6 +37,8 @@ public:
inline uint64 Change();
inline bool Dirty();
inline OpenState* GetOpenState();
void SetDelegation(Delegation* delegation);
void RecallDelegation(bool truncate = false);
void RecallReadDelegation();
@@ -230,5 +232,12 @@ Inode::Dirty()
}
inline OpenState*
Inode::GetOpenState()
{
return fOpenState;
}
#endif // INODE_H
@@ -252,7 +252,6 @@ Inode::CloseAttr(OpenAttrCookie* cookie)
fFileSystem->RemoveDelegation(cookie->fOpenState->fDelegation);
delete cookie->fOpenState->fDelegation;
delete cookie->fOpenState;
return B_OK;
}
@@ -553,7 +553,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation)
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv, NULL, state))
if (HandleErrors(reply.NFS4Error(), serv, NULL, state, &sequence))
continue;
fFileSystem->OpenOwnerSequenceUnlock();
@@ -16,7 +16,7 @@
bool
NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
OpenStateCookie* cookie, OpenState* state)
OpenStateCookie* cookie, OpenState* state, uint32* sequence)
{
uint32 leaseTime;
@@ -67,7 +67,14 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv,
case NFS4ERR_STALE_CLIENTID:
case NFS4ERR_STALE_STATEID:
if (state != NULL) {
if (sequence != NULL)
fFileSystem->OpenOwnerSequenceUnlock(false);
fFileSystem->NFSServer()->ServerRebooted(state->fClientID);
dprintf("returned rebooted\n");
if (sequence != NULL)
*sequence = fFileSystem->OpenOwnerSequenceLock();
dprintf("locked again\n");
return true;
}
return false;
@@ -19,7 +19,8 @@ class OpenState;
class NFS4Object {
public:
bool HandleErrors(uint32 nfs4Error, RPC::Server* serv,
OpenStateCookie* cookie = NULL, OpenState* state = NULL);
OpenStateCookie* cookie = NULL, OpenState* state = NULL,
uint32* sequence = NULL);
status_t ConfirmOpen(const FileHandle& fileHandle, OpenState* state);
@@ -58,11 +58,13 @@ NFS4Server::ServerRebooted(uint64 clientId)
MutexLocker _(fFSLock);
FileSystem* fs = fFileSystems;
while (fs != NULL) {
OpenState* current = fs->OpenFilesLock();
DoublyLinkedList<OpenState>::Iterator iterator
= fs->OpenFilesLock().GetIterator();
OpenState* current = iterator.Next();
while (current != NULL) {
current->Reclaim(fClientId);
current = current->fNext;
current = iterator.Next();
}
fs->OpenFilesUnlock();
@@ -13,6 +13,7 @@
#include "FileSystem.h"
#include "Request.h"
#include "WorkQueue.h"
OpenState::OpenState()
@@ -31,7 +32,9 @@ OpenState::OpenState()
OpenState::~OpenState()
{
fFileSystem->RemoveOpenFile(this);
Close();
mutex_destroy(&fLock);
mutex_destroy(&fLocksLock);
@@ -140,9 +143,10 @@ OpenState::Reclaim(uint64 newClientID)
if (fClientID == newClientID)
return B_OK;
fClientID = newClientID;
dprintf("reclaim start\n");
_ReclaimOpen(newClientID);
_ReclaimLocks(newClientID);
dprintf("reclaim end\n");
return B_OK;
}
@@ -150,10 +154,16 @@ OpenState::Reclaim(uint64 newClientID)
status_t
OpenState::_ReclaimOpen(uint64 newClientID)
{
dprintf("reclaim %s\n", fInfo.fName);
bool confirm;
OpenDelegationData delegation;
delegation.fType = OPEN_DELEGATE_NONE;
delegation.fRecall = false;
uint32 sequence = fFileSystem->OpenOwnerSequenceLock();
OpenDelegation delegType = fDelegation != NULL ? fDelegation->Type()
: OPEN_DELEGATE_NONE;
do {
RPC::Server* server = fFileSystem->Server();
Request request(server);
@@ -162,7 +172,7 @@ OpenState::_ReclaimOpen(uint64 newClientID)
req.PutFH(fInfo.fHandle);
req.Open(CLAIM_PREVIOUS, sequence, sModeToAccess(fMode), newClientID,
OPEN4_NOCREATE, fFileSystem->OpenOwner(), NULL, NULL, 0, false,
fDelegation->Type());
delegType);
status_t result = request.Send();
if (result != B_OK) {
@@ -172,7 +182,7 @@ OpenState::_ReclaimOpen(uint64 newClientID)
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), server))
if (HandleErrors(reply.NFS4Error(), server, NULL, NULL, &sequence))
continue;
fFileSystem->OpenOwnerSequenceUnlock();
@@ -182,10 +192,19 @@ OpenState::_ReclaimOpen(uint64 newClientID)
result = reply.Open(fStateID, &fStateSeq, &confirm, &delegation);
if (result != B_OK)
return result;
break;
} while (true);
if (delegation.fRecall)
fDelegation->GiveUp();
if (fDelegation != NULL)
fDelegation->SetData(delegation);
if (delegation.fRecall) {
DelegationRecallArgs* args = new(std::nothrow) DelegationRecallArgs;
args->fDelegation = fDelegation;
args->fTruncate = false;
gWorkQueue->EnqueueJob(DelegationRecall, args);
}
if (confirm)
return ConfirmOpen(fInfo.fHandle, this);
@@ -197,6 +216,8 @@ OpenState::_ReclaimOpen(uint64 newClientID)
status_t
OpenState::_ReclaimLocks(uint64 newClientID)
{
dprintf("reclaim locks %s\n", fInfo.fName);
MutexLocker _(fLocksLock);
LockInfo* linfo = fLocks;
while (linfo != NULL) {
@@ -264,7 +285,7 @@ OpenState::Close()
ReplyInterpreter& reply = request.Reply();
if (HandleErrors(reply.NFS4Error(), serv, NULL, this))
if (HandleErrors(reply.NFS4Error(), serv, NULL, this, &sequence))
continue;
fFileSystem->OpenOwnerSequenceUnlock();
@@ -17,7 +17,8 @@
#include "NFS4Object.h"
struct OpenState : public NFS4Object, public KernelReferenceable {
struct OpenState : public NFS4Object, public KernelReferenceable,
public DoublyLinkedListLinkImpl<OpenState> {
OpenState();
~OpenState();
@@ -38,9 +39,6 @@ struct OpenState : public NFS4Object, public KernelReferenceable {
LockOwner* fLockOwners;
mutex fOwnerLock;
OpenState* fNext;
OpenState* fPrev;
LockOwner* GetLockOwner(uint32 owner);
void AddLock(LockInfo* lock);
@@ -827,6 +827,7 @@ ReplyInterpreter::_NFS4ErrorToHaiku(uint32 x)
case NFS4ERR_ISDIR: return B_IS_A_DIRECTORY;
case NFS4ERR_INVAL: return B_BAD_VALUE;
case NFS4ERR_FBIG: return B_FILE_TOO_LARGE;
case NFS4ERR_NOTSUPP: return B_UNSUPPORTED;
// ...
case NFS4ERR_DELAY:
case NFS4ERR_DENIED: