From 52aaad172fd93ba9b286d237dd299746e6458e1b Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Sun, 5 Aug 2012 22:07:44 +0200 Subject: [PATCH] nfs4: Use one open state per inode --- .../kernel/file_systems/nfs4/Cookie.cpp | 1 - src/add-ons/kernel/file_systems/nfs4/Cookie.h | 5 +- .../kernel/file_systems/nfs4/Delegation.h | 43 +++++++ .../kernel/file_systems/nfs4/Inode.cpp | 5 +- src/add-ons/kernel/file_systems/nfs4/Inode.h | 19 ++- .../kernel/file_systems/nfs4/InodeIdMap.h | 1 + .../kernel/file_systems/nfs4/InodeRegular.cpp | 117 +++++------------- .../kernel/file_systems/nfs4/NFS4Inode.cpp | 8 +- .../kernel/file_systems/nfs4/NFS4Inode.h | 5 +- .../kernel/file_systems/nfs4/NFS4Object.cpp | 15 +-- .../kernel/file_systems/nfs4/NFS4Server.cpp | 12 +- .../file_systems/nfs4/ReplyInterpreter.cpp | 4 + .../file_systems/nfs4/RequestBuilder.cpp | 15 +-- .../file_systems/nfs4/kernel_interface.cpp | 22 +++- 14 files changed, 137 insertions(+), 135 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/nfs4/Delegation.h diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp index 83d0336a8b..a2970b7a95 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp @@ -161,7 +161,6 @@ OpenFileCookie::GetLockOwner(uint32 owner) if (current == NULL) return NULL; - current->fClientId = fClientID; current->fNext = fLockOwners; if (fLockOwners != NULL) fLockOwners->fPrev = current; diff --git a/src/add-ons/kernel/file_systems/nfs4/Cookie.h b/src/add-ons/kernel/file_systems/nfs4/Cookie.h index baeca6706d..4af8899333 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Cookie.h +++ b/src/add-ons/kernel/file_systems/nfs4/Cookie.h @@ -71,10 +71,7 @@ struct Cookie { }; struct OpenFileCookie : public Cookie { - uint64 fClientID; - - OpenState* fReadState; - OpenState* fWriteState; + OpenState* fOpenState; uint32 fMode; diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.h b/src/add-ons/kernel/file_systems/nfs4/Delegation.h new file mode 100644 index 0000000000..31fea04344 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef DELEGATION_H +#define DELEGATION_H + + +#include +#include + +#include "NFS4Object.h" + + +class Delegation : public NFS4Object { +public: + Delegation(OpenDelegationData data, Inode* inode, + uint64 clientID); + ~Delegation(); + + status_t Write(void* buffer, uint32* size); + status_t Read(void* buffer, uint32* size); + + // TODO: locks + + status_t Reclaim(uint64 newClientID); + + status_t GiveUp(bool flush); + +private: + uint64 fClientID; + OpenDelegationData fData; + Inode* fInode; + + rw_lock fLock; +}; + + +#endif // DELEGATION_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 007890e310..edfbddffde 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -24,8 +24,7 @@ Inode::Inode() : fCache(NULL), fFileCache(NULL), - fWriteState(NULL), - fReadState(NULL), + fOpenState(NULL), fWriteDirty(false) { mutex_init(&fStateLock, NULL); @@ -530,7 +529,7 @@ Inode::WriteStat(const struct stat* st, uint32 mask) } MutexLocker stateLocker(fStateLock); - result = NFS4Inode::WriteStat(fWriteState, attr, i); + result = NFS4Inode::WriteStat(fOpenState, attr, i); stateLocker.Unlock(); fMetaCache.InvalidateStat(); diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index e4bfa9ac6b..58250e7521 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -14,6 +14,8 @@ #include "OpenState.h" +class Delegation; + class Inode : public NFS4Inode { public: static status_t CreateInode(FileSystem* fs, const FileInfo& fi, @@ -25,6 +27,8 @@ public: inline const char* Name() const; inline FileSystem* GetFileSystem() const; + inline void SetOpenState(OpenState* state); + inline void* FileCache(); status_t RevalidateFileCache(); @@ -93,17 +97,20 @@ protected: static inline ino_t FileIdToInoT(uint64 fileid); +private: uint32 fType; MetadataCache fMetaCache; DirectoryCache* fCache; + rw_lock fDelegationLock; + Delegation* fDelegation; + uint64 fChange; void* fFileCache; mutex fFileCacheLock; - OpenState* fWriteState; - OpenState* fReadState; + OpenState* fOpenState; mutex fStateLock; bool fWriteDirty; @@ -156,5 +163,13 @@ Inode::FileCache() } +inline void +Inode::SetOpenState(OpenState* state) +{ + MutexLocker _(fStateLock); + fOpenState = state; +} + + #endif // INODE_H diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h index 63ec1b07b3..2a29e07942 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h +++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h @@ -52,6 +52,7 @@ inline status_t InodeIdMap::AddEntry(const FileInfo& fi, ino_t id) { MutexLocker _(fLock); + fMap.Remove(id); return fMap.Insert(id, fi); } diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 51d41229c9..c82c507da5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -70,44 +70,19 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, cookie->fLocks = NULL; MutexLocker _(fStateLock); - int openMode = mode & O_RWMASK; - if (openMode == O_WRONLY || openMode == O_RDWR) { - OpenState* state = new OpenState; - status_t result = CreateState(name, O_WRONLY, perms, state); - if (result != B_OK) - return result; + OpenState* state = new OpenState; + status_t result = CreateState(name, mode, perms, state); + if (result != B_OK) + return result; - fWriteState = state; - *id = FileIdToInoT(cookie->fWriteState->fInfo.fFileId); - cookie->fWriteState = fWriteState; - } + cookie->fOpenState = state; + fOpenState = state; - if (openMode == O_RDONLY || openMode == O_RDWR) { - OpenState* state = new OpenState; - state->fInfo = fInfo; - state->fFileSystem = fFileSystem; - - status_t result; - if (openMode == O_RDWR) - result = OpenFile(state, O_RDONLY); - else - result = CreateState(name, O_RDONLY, perms, state); - - if (result != B_OK) { - if (fWriteState != NULL) - if (fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - return result; - } - - fReadState = state; - *id = FileIdToInoT(cookie->fReadState->fInfo.fFileId); - cookie->fReadState = fReadState; - } + *id = FileIdToInoT(state->fInfo.fFileId); + cookie->fOpenState = fOpenState; cookie->fFileSystem = fFileSystem; - cookie->fClientID = fFileSystem->NFSServer()->ClientId(); fFileSystem->AddOpenFile(cookie); fFileSystem->Root()->MakeInfoInvalid(); @@ -120,55 +95,33 @@ status_t Inode::Open(int mode, OpenFileCookie* cookie) { MutexLocker _(fStateLock); - int openMode = mode & O_RWMASK; - if (openMode == O_WRONLY || openMode == O_RDWR) { - if (fWriteState == NULL) { - OpenState* state = new OpenState; - if (state == NULL) - return B_NO_MEMORY; + if (fOpenState == NULL) { + OpenState* state = new OpenState; + if (state == NULL) + return B_NO_MEMORY; - state->fInfo = fInfo; - state->fFileSystem = fFileSystem; - status_t result = OpenFile(state, O_WRONLY); + state->fInfo = fInfo; + state->fFileSystem = fFileSystem; + status_t result = OpenFile(state, mode, NULL); + if (result != B_OK) + return result; + + fOpenState = state; + } else { + int newMode = mode & O_RWMASK; + int oldMode = fOpenState->fMode & O_RWMASK; + if (oldMode != newMode && oldMode != O_RDWR) { + status_t result = OpenFile(fOpenState, O_RDWR, NULL); if (result != B_OK) return result; - - fWriteState = state; - } else - fWriteState->AcquireReference(); - - cookie->fWriteState = fWriteState; + fOpenState->fMode = O_RDWR; + } + fOpenState->AcquireReference(); } - if (openMode == O_RDONLY || openMode == O_RDWR) { - if (fReadState == NULL) { - OpenState* state = new OpenState; - if (state == NULL) { - if (fWriteState != NULL) - if (fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - return B_NO_MEMORY; - } + cookie->fOpenState = fOpenState; - state->fInfo = fInfo; - state->fFileSystem = fFileSystem; - status_t result = OpenFile(state, O_RDONLY); - if (result != B_OK) { - if (fWriteState != NULL) - if (fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - return result; - } - - fReadState = state; - } else - fReadState->AcquireReference(); - - cookie->fReadState = fReadState; - } - - cookie->fClientID = fFileSystem->NFSServer()->ClientId(); cookie->fFileSystem = fFileSystem; cookie->fMode = mode; cookie->fLocks = NULL; @@ -185,13 +138,9 @@ Inode::Close(OpenFileCookie* cookie) fFileSystem->RemoveOpenFile(cookie); MutexLocker _(fStateLock); - if (cookie->fWriteState != NULL) - if (cookie->fWriteState->ReleaseReference() == 1) - fWriteState = NULL; - - if (cookie->fReadState != NULL) - if (cookie->fReadState->ReleaseReference() == 1) - fReadState = NULL; + if (cookie->fOpenState != NULL) + if (cookie->fOpenState->ReleaseReference() == 1) + fOpenState = NULL; return B_OK; } @@ -207,7 +156,7 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length, status_t result; while (size < *_length && !*eof) { uint32 len = *_length - size; - result = ReadFile(cookie, fReadState, pos + size, &len, + result = ReadFile(cookie, fOpenState, pos + size, &len, reinterpret_cast(buffer) + size, eof); if (result != B_OK) { if (size == 0) @@ -236,7 +185,7 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, while (size < *_length) { uint32 len = *_length - size; - status_t result = WriteFile(cookie, fWriteState, pos + size, &len, + status_t result = WriteFile(cookie, fOpenState, pos + size, &len, buffer + size); if (result != B_OK) { if (size == 0) diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp index 1c6722b3ef..c2208fb8af 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.cpp @@ -493,9 +493,8 @@ NFS4Inode::CreateFile(const char* name, int mode, int perms, status_t -NFS4Inode::OpenFile(OpenState* state, int mode) +NFS4Inode::OpenFile(OpenState* state, int mode, OpenDelegationData* delegation) { - OpenDelegationData delegation; bool confirm; status_t result; uint32 sequence = fFileSystem->OpenOwnerSequenceLock(); @@ -571,7 +570,7 @@ NFS4Inode::OpenFile(OpenState* state, int mode) reply.PutFH(); result = reply.Open(state->fStateID, &state->fStateSeq, &confirm, - &delegation); + delegation); FileHandle handle; reply.GetFH(&handle); @@ -587,9 +586,6 @@ NFS4Inode::OpenFile(OpenState* state, int mode) if (confirm) return ConfirmOpen(fInfo.fHandle, state); - if (delegation.fType != OPEN_DELEGATE_NONE) - dprintf("GOT A DELEGATION!\n"); - return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h index 027f6a4917..dbcf90a1c8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Inode.h @@ -33,7 +33,7 @@ protected: status_t LookUp(const char* name, uint64* change, uint64* fileID, FileHandle* handle); - status_t Link(Inode* dir, const char* name, + status_t Link(Inode* dir, const char* name,s ChangeInfo* changeInfo); static status_t Rename(Inode* from, Inode* to, const char* fromName, @@ -47,7 +47,8 @@ protected: status_t CreateFile(const char* name, int mode, int perms, OpenState* state, ChangeInfo* changeInfo, uint64* fileID, FileHandle* handle); - status_t OpenFile(OpenState* state, int mode); + status_t OpenFile(OpenState* state, int mode, + OpenDelegationData* delegation); status_t ReadFile(OpenFileCookie* cookie, OpenState* state, uint64 position, uint32* length, void* buffer, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp index 073fd01c6c..327c075246 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Object.cpp @@ -19,6 +19,9 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, { uint32 leaseTime; + if (cookie != NULL) + state = cookie->fOpenState; + switch (nfs4Error) { case NFS4_OK: return false; @@ -62,10 +65,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, // server has rebooted, reclaim share and try again case NFS4ERR_STALE_CLIENTID: case NFS4ERR_STALE_STATEID: - if (cookie != NULL) { - fFileSystem->NFSServer()->ServerRebooted(cookie->fClientID); - return true; - } else if (state != NULL) { + if (state != NULL) { fFileSystem->NFSServer()->ServerRebooted(state->fClientID); return true; } @@ -85,10 +85,7 @@ NFS4Object::HandleErrors(uint32 nfs4Error, RPC::Server* serv, // lease has expired case NFS4ERR_EXPIRED: - if (cookie != NULL) { - fFileSystem->NFSServer()->ClientId(cookie->fClientID, true); - return true; - } else if (state != NULL) { + if (state != NULL) { fFileSystem->NFSServer()->ClientId(state->fClientID, true); return true; } @@ -121,7 +118,7 @@ NFS4Object::ConfirmOpen(const FileHandle& fh, OpenState* state) ReplyInterpreter& reply = request.Reply(); - if (HandleErrors(reply.NFS4Error(), serv)) + if (HandleErrors(reply.NFS4Error(), serv, NULL, state)) continue; fFileSystem->OpenOwnerSequenceUnlock(); diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 412a653866..ec38c3af13 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -59,7 +59,6 @@ NFS4Server::ServerRebooted(uint64 clientId) while (fs != NULL) { OpenFileCookie* current = fs->OpenFilesLock(); while (current != NULL) { - current->fClientID = fClientId; _ReclaimOpen(current); _ReclaimLocks(current); current = current->fNext; @@ -75,10 +74,8 @@ NFS4Server::ServerRebooted(uint64 clientId) status_t NFS4Server::_ReclaimOpen(OpenFileCookie* cookie) { - if (cookie->fWriteState != NULL) - cookie->fWriteState->Reclaim(fClientId); - if (cookie->fReadState != NULL) - cookie->fReadState->Reclaim(fClientId); + if (cookie->fOpenState != NULL) + cookie->fOpenState->Reclaim(fClientId); return B_OK; } @@ -100,10 +97,7 @@ NFS4Server::_ReclaimLocks(OpenFileCookie* cookie) Request request(fServer); RequestBuilder& req = request.Builder(); - if (cookie->fWriteState != NULL) - req.PutFH(cookie->fWriteState->fInfo.fHandle); - else - req.PutFH(cookie->fReadState->fInfo.fHandle); + req.PutFH(cookie->fOpenState->fInfo.fHandle); req.Lock(cookie, linfo, true); status_t result = request.Send(); diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index 2b74de3b17..b26082d78f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -298,6 +298,10 @@ ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm, // delegation info uint32 delegation = fReply->Stream().GetUInt(); + OpenDelegationData data; + if (delegData == NULL) + delegData = &data; + if (delegation == OPEN_DELEGATE_NONE) { delegData->fType = OPEN_DELEGATE_NONE; return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK; diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index c6a0e80cda..c05b873a11 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -173,14 +173,11 @@ void RequestBuilder::_GenerateLockOwner(XDR::WriteStream& stream, OpenFileCookie* cookie, LockOwner* owner) { - stream.AddUHyper(cookie->fClientID); + stream.AddUHyper(cookie->fOpenState->fClientID); uint64 lockOwner[2]; lockOwner[0] = owner->fOwner; - if (cookie->fWriteState != NULL) - lockOwner[1] = cookie->fWriteState->fInfo.fFileId; - else - lockOwner[1] = cookie->fReadState->fInfo.fFileId; + lockOwner[1] = cookie->fOpenState->fInfo.fFileId; stream.AddOpaque(lockOwner, sizeof(lockOwner)); } @@ -208,11 +205,7 @@ RequestBuilder::Lock(OpenFileCookie* cookie, LockInfo* lock, uint32 sequence, fRequest->Stream().AddBoolean(true); // new lock owner // open seq stateid - OpenState* state; - if (lock->fType == READ_LT || lock->fType == READW_LT) - state = cookie->fReadState; - else - state = cookie->fWriteState; + OpenState* state = cookie->fOpenState; fRequest->Stream().AddUInt(sequence); fRequest->Stream().AddUInt(state->fStateSeq); @@ -258,7 +251,7 @@ RequestBuilder::LockT(LockType type, uint64 pos, uint64 len, fRequest->Stream().AddUHyper(pos); fRequest->Stream().AddUHyper(len); - fRequest->Stream().AddUHyper(cookie->fClientID); + fRequest->Stream().AddUHyper(cookie->fOpenState->fClientID); uint32 owner = find_thread(NULL); fRequest->Stream().AddOpaque(&owner, sizeof(owner)); diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index 95b8bd87eb..d1a447bc09 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -400,10 +400,24 @@ nfs4_create(fs_volume* volume, fs_vnode* dir, const char* name, int openMode, return result; } - void* ptr; - result = get_vnode(volume, *_newVnodeID, &ptr); - if (result != B_OK) - delete cookie; + Inode* child; + result = get_vnode(volume, *_newVnodeID, reinterpret_cast(&child)); + if (result != B_OK) { + result = inode->GetFileSystem()->GetInode(*_newVnodeID, &child); + if (result != B_OK) { + delete cookie; + return result; + } + + result = new_vnode(volume, *_newVnodeID, child, &gNFSv4VnodeOps); + if (result != B_OK) { + delete child; + delete cookie; + return result; + } + } + + child->SetOpenState(cookie->fOpenState); return result; }