From 4a153753100503cf374d01079fb29ca83d3ac44b Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Mon, 6 Aug 2012 02:03:28 +0200 Subject: [PATCH] nfs4: Return delegations when asked to --- .../kernel/file_systems/nfs4/Delegation.cpp | 70 +++++++++++++++ .../kernel/file_systems/nfs4/Delegation.h | 21 ++++- .../kernel/file_systems/nfs4/FileInfo.h | 21 +++++ .../kernel/file_systems/nfs4/FileSystem.cpp | 42 +++++++++ .../kernel/file_systems/nfs4/FileSystem.h | 11 +++ .../kernel/file_systems/nfs4/Inode.cpp | 29 +++++++ src/add-ons/kernel/file_systems/nfs4/Inode.h | 3 + .../kernel/file_systems/nfs4/InodeRegular.cpp | 16 +++- src/add-ons/kernel/file_systems/nfs4/Jamfile | 3 + .../kernel/file_systems/nfs4/NFS4Defs.h | 5 ++ .../kernel/file_systems/nfs4/NFS4Server.cpp | 68 +++++++++++++++ .../kernel/file_systems/nfs4/NFS4Server.h | 8 ++ .../kernel/file_systems/nfs4/RPCCallback.cpp | 11 ++- .../kernel/file_systems/nfs4/RPCCallback.h | 4 + .../file_systems/nfs4/RPCCallbackRequest.cpp | 6 ++ .../file_systems/nfs4/RPCCallbackServer.cpp | 9 +- .../kernel/file_systems/nfs4/RPCServer.cpp | 2 +- .../kernel/file_systems/nfs4/RPCServer.h | 3 + .../kernel/file_systems/nfs4/ReplyBuilder.cpp | 85 +++++++++++++++++++ .../kernel/file_systems/nfs4/ReplyBuilder.h | 43 ++++++++++ .../file_systems/nfs4/ReplyInterpreter.h | 8 ++ .../file_systems/nfs4/RequestBuilder.cpp | 21 +++++ .../kernel/file_systems/nfs4/RequestBuilder.h | 1 + .../file_systems/nfs4/RequestInterpreter.cpp | 52 ++++++++++++ .../file_systems/nfs4/RequestInterpreter.h | 54 ++++++++++++ 25 files changed, 583 insertions(+), 13 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/nfs4/Delegation.cpp create mode 100644 src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp create mode 100644 src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h create mode 100644 src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp create mode 100644 src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp new file mode 100644 index 0000000000..299cf2143e --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include "Delegation.h" + +#include "Inode.h" +#include "Request.h" + + +Delegation::Delegation(const OpenDelegationData& data, Inode* inode, + uint64 clientID) + : + fClientID(clientID), + fData(data), + fInode(inode) +{ + rw_lock_init(&fLock, NULL); +} + + +Delegation::~Delegation() +{ + rw_lock_destroy(&fLock); +} + +status_t +Delegation::GiveUp(bool truncate) +{ + if (!truncate) { + // save buffers + } + + ReturnDelegation(); + + return B_OK; +} + + +status_t +Delegation::ReturnDelegation() +{ + do { + RPC::Server* serv = fFileSystem->Server(); + Request request(serv); + RequestBuilder& req = request.Builder(); + + req.PutFH(fInfo.fHandle); + req.DelegReturn(fData.fStateID, fData.fStateSeq); + + status_t result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter& reply = request.Reply(); + + if (HandleErrors(reply.NFS4Error(), serv)) + continue; + + reply.PutFH(); + + return reply.DelegReturn(); + } while (true); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Delegation.h b/src/add-ons/kernel/file_systems/nfs4/Delegation.h index 31fea04344..d54da15a07 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Delegation.h +++ b/src/add-ons/kernel/file_systems/nfs4/Delegation.h @@ -15,9 +15,12 @@ #include "NFS4Object.h" -class Delegation : public NFS4Object { +class Inode; + +class Delegation : public NFS4Object, + public DoublyLinkedListLinkImpl { public: - Delegation(OpenDelegationData data, Inode* inode, + Delegation(const OpenDelegationData& data, Inode* inode, uint64 clientID); ~Delegation(); @@ -28,7 +31,12 @@ public: status_t Reclaim(uint64 newClientID); - status_t GiveUp(bool flush); + status_t GiveUp(bool truncate); + + inline Inode* GetInode(); + +protected: + status_t ReturnDelegation(); private: uint64 fClientID; @@ -39,5 +47,12 @@ private: }; +inline Inode* +Delegation::GetInode() +{ + return fInode; +} + + #endif // DELEGATION_H diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h index 28b541218b..5cd0f2af3c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileInfo.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h @@ -24,6 +24,9 @@ struct FileHandle { inline FileHandle(); inline FileHandle(const FileHandle& fh); inline FileHandle& operator=(const FileHandle& fh); + + inline bool operator>(const FileHandle& handle) const; + inline bool operator<(const FileHandle& handle) const; }; @@ -87,6 +90,24 @@ FileHandle::operator=(const FileHandle& fh) } +inline bool +FileHandle::operator>(const FileHandle& handle) const +{ + if (fSize > handle.fSize) + return true; + return memcmp(fData, handle.fData, fSize) > 0; +} + + +inline bool +FileHandle::operator<(const FileHandle& handle) const +{ + if (fSize < handle.fSize) + return true; + return memcmp(fData, handle.fData, fSize) < 0; +} + + inline FileInfo::FileInfo() : diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp index f4eb9906d4..d5e3d8bf26 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.cpp @@ -38,6 +38,7 @@ FileSystem::FileSystem() mutex_init(&fOpenOwnerLock, NULL); mutex_init(&fOpenLock, NULL); + mutex_init(&fDelegationLock, NULL); } @@ -45,6 +46,7 @@ FileSystem::~FileSystem() { NFSServer()->RemoveFileSystem(this); + mutex_destroy(&fDelegationLock); mutex_destroy(&fOpenLock); mutex_destroy(&fOpenOwnerLock); @@ -308,3 +310,43 @@ FileSystem::RemoveOpenFile(OpenFileCookie* cookie) NFSServer()->DecUsage(); } + +void +FileSystem::AddDelegation(Delegation* delegation) +{ + MutexLocker _(fDelegationLock); + + fOpenDelegations.InsertBefore(fOpenDelegations.Head(), delegation); + + fHandleToDelegation.Remove(delegation->fInfo.fHandle); + fHandleToDelegation.Insert(delegation->fInfo.fHandle, delegation); + + NFSServer()->IncUsage(); +} + + +void +FileSystem::RemoveDelegation(Delegation* delegation) +{ + MutexLocker _(fDelegationLock); + + fOpenDelegations.Remove(delegation); + fHandleToDelegation.Remove(delegation->fInfo.fHandle); + + NFSServer()->DecUsage(); +} + + +Delegation* +FileSystem::GetDelegation(const FileHandle& handle) +{ + MutexLocker _(fDelegationLock); + + AVLTreeMap::Iterator it; + it = fHandleToDelegation.Find(handle); + if (!it.HasCurrent()) + return NULL; + + return it.Current(); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h index 4c5df282e4..7814f8e667 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -10,6 +10,7 @@ #include "CacheRevalidator.h" +#include "Delegation.h" #include "InodeIdMap.h" #include "NFS4Defs.h" #include "NFS4Server.h" @@ -35,6 +36,12 @@ public: void AddOpenFile(OpenFileCookie* cookie); void RemoveOpenFile(OpenFileCookie* cookie); + OpenFileCookie* DelegationsLock(); + void DelegationsUnlock(); + void AddDelegation(Delegation* delegation); + void RemoveDelegation(Delegation* delegation); + Delegation* GetDelegation(const FileHandle& handle); + inline CacheRevalidator& Revalidator(); inline bool IsAttrSupported(Attribute attr) const; @@ -62,6 +69,10 @@ private: CacheRevalidator fCacheRevalidator; + DoublyLinkedList fOpenDelegations; + mutex fDelegationLock; + AVLTreeMap fHandleToDelegation; + OpenFileCookie* fOpenFiles; uint32 fOpenCount; mutex fOpenLock; diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index a573f4989d..0f0846e7e8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -23,11 +23,13 @@ Inode::Inode() : fCache(NULL), + fDelegation(NULL), fFileCache(NULL), fMaxFileSize(0), fOpenState(NULL), fWriteDirty(false) { + rw_lock_init(&fDelegationLock, NULL); mutex_init(&fStateLock, NULL); mutex_init(&fFileCacheLock, NULL); } @@ -121,12 +123,16 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode) Inode::~Inode() { + if (fDelegation != NULL) + RecallDelegation(); + if (fFileCache != NULL) file_cache_delete(fFileCache); delete fCache; mutex_destroy(&fStateLock); mutex_destroy(&fFileCacheLock); + rw_lock_destroy(&fDelegationLock); } @@ -721,3 +727,26 @@ Inode::ChildAdded(const char* name, uint64 fileID, return fFileSystem->InoIdMap()->AddEntry(fi, FileIdToInoT(fileID)); } + +void +Inode::SetDelegation(Delegation* delegation) +{ + WriteLocker _(fDelegationLock); + fDelegation = delegation; + fFileSystem->AddDelegation(delegation); +} + + +void +Inode::RecallDelegation(bool truncate) +{ + WriteLocker _(fDelegationLock); + if (fDelegation == NULL) + return; + + fDelegation->GiveUp(truncate); + fFileSystem->RemoveDelegation(fDelegation); + delete fDelegation; + fDelegation = NULL; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index a44c12b584..4c56e75289 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -34,6 +34,9 @@ public: inline uint64 MaxFileSize(); + void SetDelegation(Delegation* delegation); + void RecallDelegation(bool truncate = false); + status_t LookUp(const char* name, ino_t* id); status_t Access(int mode); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 34ca35e1f8..920821548b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -96,6 +96,8 @@ Inode::Open(int mode, OpenFileCookie* cookie) { MutexLocker _(fStateLock); + OpenDelegationData data; + data.fType = OPEN_DELEGATE_NONE; if (fOpenState == NULL) { OpenState* state = new OpenState; if (state == NULL) @@ -103,7 +105,7 @@ Inode::Open(int mode, OpenFileCookie* cookie) state->fInfo = fInfo; state->fFileSystem = fFileSystem; - status_t result = OpenFile(state, mode, NULL); + status_t result = OpenFile(state, mode, &data); if (result != B_OK) return result; @@ -112,7 +114,7 @@ Inode::Open(int mode, OpenFileCookie* cookie) 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); + status_t result = OpenFile(fOpenState, O_RDWR, &data); if (result != B_OK) return result; fOpenState->fMode = O_RDWR; @@ -128,6 +130,16 @@ Inode::Open(int mode, OpenFileCookie* cookie) fFileSystem->AddOpenFile(cookie); + if (data.fType != OPEN_DELEGATE_NONE) { + Delegation* delegation + = new(std::nothrow) Delegation(data, this, fOpenState->fClientID); + if (delegation != NULL) { + delegation->fInfo = fOpenState->fInfo; + delegation->fFileSystem = fFileSystem; + SetDelegation(delegation); + } + } + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile b/src/add-ons/kernel/file_systems/nfs4/Jamfile index b6aeed821e..a3a41946f2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Jamfile +++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile @@ -7,6 +7,7 @@ KernelAddon nfs4 : CacheRevalidator.cpp Cookie.cpp Connection.cpp + Delegation.cpp DirectoryCache.cpp FileInfo.cpp FileSystem.cpp @@ -20,9 +21,11 @@ KernelAddon nfs4 : NFS4Object.cpp NFS4Server.cpp OpenState.cpp + ReplyBuilder.cpp ReplyInterpreter.cpp Request.cpp RequestBuilder.cpp + RequestInterpreter.cpp RootInode.cpp RPCAuth.cpp RPCCall.cpp diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 1887ee2430..c162462178 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -25,11 +25,16 @@ enum CallbackProcedure { CallbackProcCompound = 1 }; +enum CallbackOpcode { + OpCallbackRecall = 4 +}; + enum Opcode { OpAccess = 3, OpClose = 4, OpCommit = 5, OpCreate = 6, + OpDelegReturn = 8, OpGetAttr = 9, OpGetFH = 10, OpLink = 11, diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index ec38c3af13..88fbce1041 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -315,3 +315,71 @@ NFS4Server::_RenewalThreadStart(void* ptr) return server->_Renewal(); } + +status_t +NFS4Server::ProcessCallback(RPC::CallbackRequest* request, + Connection* connection) +{ + RequestInterpreter req(request); + ReplyBuilder reply(request->XID()); + + status_t result; + uint32 count = req.OperationCount(); + + for (uint32 i = 0; i < count; i++) { + switch (req.Operation()) { + case OpCallbackRecall: + result = CallbackRecall(&req, &reply); + break; + default: + result = B_NOT_SUPPORTED; + } + + if (result != B_OK) + break; + } + + XDR::WriteStream& stream = reply.Reply()->Stream(); + connection->Send(stream.Buffer(), stream.Size()); + + return B_OK; +} + + +status_t +NFS4Server::CallbackRecall(RequestInterpreter* request, ReplyBuilder* reply) +{ + uint32 stateID[3]; + uint32 stateSeq; + bool truncate; + FileHandle handle; + + status_t result = request->Recall(&handle, truncate, &stateSeq, stateID); + if (result != B_OK) + return result; + + MutexLocker locker(fFSLock); + + Delegation* delegation = NULL; + FileSystem* current = fFileSystems; + while (current != NULL) { + delegation = current->GetDelegation(handle); + if (delegation != NULL) + break; + + current = current->fNext; + } + locker.Unlock(); + + if (delegation == NULL) { + reply->Recall(B_FILE_NOT_FOUND); + return B_FILE_NOT_FOUND; + } + + // TODO: should be asynchronous + delegation->GetInode()->RecallDelegation(truncate); + + reply->Recall(B_OK); + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index 46134e8b1b..4d37a960a8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -11,6 +11,8 @@ #include +#include "ReplyBuilder.h" +#include "RequestInterpreter.h" #include "RPCServer.h" @@ -34,6 +36,12 @@ public: uint64 ClientId(uint64 prevId = 0, bool forceNew = false); inline uint32 LeaseTime(); + + virtual status_t ProcessCallback(RPC::CallbackRequest* request, + Connection* connection); + + status_t CallbackRecall(RequestInterpreter* request, + ReplyBuilder* reply); private: status_t _ReclaimOpen(OpenFileCookie* cookie); status_t _ReclaimLocks(OpenFileCookie* cookie); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp index 70da61c58e..ddf5b63b01 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.cpp @@ -10,15 +10,22 @@ #include "RPCCallback.h" #include "RPCCallbackRequest.h" +#include "RPCServer.h" using namespace RPC; +Callback::Callback(Server* server) + : + fServer(server) +{ +} + + status_t Callback::EnqueueRequest(CallbackRequest* request, Connection* connection) { - dprintf("GOT A CALLBACK REQUEST %x\n", (int)request->XID()); - return B_OK; + return fServer->PrivateData()->ProcessCallback(request, connection); } diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h index 66d60ac116..b729156bd0 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallback.h @@ -15,9 +15,12 @@ namespace RPC { class CallbackRequest; +class Server; class Callback { public: + Callback(Server* server); + inline void SetID(int32 id); inline int32 ID(); @@ -25,6 +28,7 @@ public: Connection* connection); private: + Server* fServer; int32 fID; }; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp index 4b10efb928..90fce4d550 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackRequest.cpp @@ -45,7 +45,10 @@ CallbackRequest::CallbackRequest(void *buffer, int size) fProcedure = fStream.GetUInt(); + fStream.GetUInt(); fStream.GetOpaque(NULL); + + fStream.GetUInt(); fStream.GetOpaque(NULL); if (fProcedure == CallbackProcCompound) { @@ -54,6 +57,9 @@ CallbackRequest::CallbackRequest(void *buffer, int size) return; fID = fStream.GetUInt(); + + fRPCError = SUCCESS; + fError = B_OK; } else if (fProcedure == CallbackProcNull) { fRPCError = SUCCESS; fError = B_OK; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp index 5a64700092..b007a3ba99 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCCallbackServer.cpp @@ -26,7 +26,7 @@ CallbackServer::CallbackServer() fConnectionList(NULL), fListener(NULL), fThreadRunning(false), - fCallbackArray(NULL), + //fCallbackArray(NULL), fArraySize(0), fFreeSlot(-1) { @@ -40,7 +40,7 @@ CallbackServer::~CallbackServer() { StopServer(); - free(fCallbackArray); + //free(fCallbackArray); rw_lock_destroy(&fArrayLock); mutex_destroy(&fThreadLock); mutex_destroy(&fConnectionLock); @@ -68,7 +68,7 @@ CallbackServer::RegisterCallback(Callback* callback) for (uint32 i = fArraySize; i < newSize; i++) array[i].fNext = i + 1; - array[fArraySize * 2 - 1].fNext = -1; + array[newSize - 1].fNext = -1; fCallbackArray = array; fFreeSlot = fArraySize; @@ -240,7 +240,7 @@ CallbackServer::ConnectionThread(ConnectionEntry* entry) if (request == NULL || request->Error() != B_OK) { free(buffer); continue; - } else if (request != NULL) { + } else if (request != NULL && request->Error() != B_OK) { reply = CallbackReply::Create(request->XID(), request->RPCError()); if (reply != NULL) { connection->Send(reply->Stream().Buffer(), @@ -251,7 +251,6 @@ CallbackServer::ConnectionThread(ConnectionEntry* entry) continue; } - switch (request->Procedure()) { case CallbackProcCompound: GetCallback(request->ID())->EnqueueRequest(request, connection); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index fce6f5aa3b..70876f6682 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -228,7 +228,7 @@ Server::GetCallback() { MutexLocker _(fCallbackLock); if (fCallback == NULL) { - fCallback = new Callback; + fCallback = new(std::nothrow) Callback(this); gRPCCallbackServer->RegisterCallback(fCallback); } diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h index ddcb80e423..f4afd7f02e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h @@ -48,6 +48,9 @@ private: class ProgramData { public: + virtual status_t ProcessCallback(CallbackRequest* request, + Connection* connection) = 0; + virtual ~ProgramData() { } }; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp new file mode 100644 index 0000000000..e18a4a64ad --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include "ReplyBuilder.h" + +#include "NFS4Defs.h" +#include "RPCCallbackReply.h" + + +ReplyBuilder::ReplyBuilder(uint32 xid) + : + fStatus(B_OK), + fOpCount(0), + fReply(RPC::CallbackReply::Create(xid)) +{ + _InitHeader(); +} + + +ReplyBuilder::~ReplyBuilder() +{ + delete fReply; +} + + +void +ReplyBuilder::_InitHeader() +{ + fStatusPosition = fReply->Stream().Current(); + fReply->Stream().AddUInt(0); + + fReply->Stream().AddOpaque(NULL, 0); + + fOpCountPosition = fReply->Stream().Current(); + fReply->Stream().AddUInt(0); + +} + + +RPC::CallbackReply* +ReplyBuilder::Reply() +{ + fReply->Stream().InsertUInt(fStatusPosition, _HaikuErrorToNFS4(fStatus)); + fReply->Stream().InsertUInt(fOpCountPosition, fOpCount); + + if (fReply == NULL || fReply->Stream().Error() == B_OK) + return fReply; + else + return NULL; +} + + +status_t +ReplyBuilder::Recall(status_t status) +{ + if (fStatus != B_OK) + return B_ERROR; + + fReply->Stream().AddUInt(OpCallbackRecall); + fReply->Stream().AddUInt(_HaikuErrorToNFS4(fStatus)); + fStatus = status; + + fOpCount++; + + return B_OK; +} + + +uint32 +ReplyBuilder::_HaikuErrorToNFS4(status_t error) +{ + switch (error) { + case B_OK: return NFS4_OK; + case B_FILE_NOT_FOUND: return NFS4ERR_BADHANDLE; + case B_NOT_SUPPORTED: return NFS4ERR_OP_ILLEGAL; + default: return NFS4ERR_RESOURCE; + } +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.h new file mode 100644 index 0000000000..be85416261 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyBuilder.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 REPLYBUILDER_H +#define REPLYBUILDER_H + + +#include + +#include "RPCCallbackReply.h" +#include "XDR.h" + + +class ReplyBuilder { +public: + ReplyBuilder(uint32 xid); + ~ReplyBuilder(); + + RPC::CallbackReply* Reply(); + + status_t Recall(status_t status); + +private: + void _InitHeader(); + + static uint32 _HaikuErrorToNFS4(status_t error); + + status_t fStatus; + XDR::Stream::Position fStatusPosition; + + uint32 fOpCount; + XDR::Stream::Position fOpCountPosition; + + RPC::CallbackReply* fReply; +}; + + +#endif // REPLYBUILDER_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 892e34cc41..986fcd8a7c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -71,6 +71,7 @@ public: status_t Close(); status_t Commit(); status_t Create(uint64* before, uint64* after, bool& atomic); + inline status_t DelegReturn(); status_t GetAttr(AttrValue** attrs, uint32* count); status_t GetFH(FileHandle* fh); status_t Link(uint64* before, uint64* after, bool& atomic); @@ -150,6 +151,13 @@ ReplyInterpreter::NFS4Error() } +inline status_t +ReplyInterpreter::DelegReturn() +{ + return _OperationError(OpDelegReturn); +} + + inline status_t ReplyInterpreter::LookUp() { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index c05b873a11..17d825946b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -137,6 +137,27 @@ RequestBuilder::Create(FileType type, const char* name, AttrValue* attr, } +status_t +RequestBuilder::DelegReturn(const uint32* id, uint32 seq) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpDelegReturn); + + fRequest->Stream().AddUInt(seq); + fRequest->Stream().AddUInt(id[0]); + fRequest->Stream().AddUInt(id[1]); + fRequest->Stream().AddUInt(id[2]); + + fOpCount++; + + return B_OK; +} + + status_t RequestBuilder::GetAttr(Attribute* attrs, uint32 count) { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 13db57de2b..d850c3c176 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -37,6 +37,7 @@ public: status_t Create(FileType type, const char* name, AttrValue* attr, uint32 count, const char* path = NULL); + status_t DelegReturn(const uint32* id, uint32 seq); status_t GetAttr(Attribute* attrs, uint32 count); status_t GetFH(); status_t Link(const char* name); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp new file mode 100644 index 0000000000..c129cde78d --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include "RequestInterpreter.h" + +#include + +#include + + +RequestInterpreter::RequestInterpreter(RPC::CallbackRequest* request) + : + fRequest(request) +{ + fOperationCount = fRequest->Stream().GetUInt(); +} + + +RequestInterpreter::~RequestInterpreter() +{ + delete fRequest; +} + + +status_t +RequestInterpreter::Recall(FileHandle* handle, bool& truncate, uint32* stateSeq, + uint32* stateID) +{ + if (fLastOperation != OpCallbackRecall) + return B_BAD_VALUE; + + *stateSeq = fRequest->Stream().GetUInt(); + stateID[0] = fRequest->Stream().GetUInt(); + stateID[1] = fRequest->Stream().GetUInt(); + stateID[2] = fRequest->Stream().GetUInt(); + + truncate = fRequest->Stream().GetBoolean(); + + uint32 size; + const void* ptr = fRequest->Stream().GetOpaque(&size); + handle->fSize = size; + memcpy(handle->fData, ptr, size); + + return fRequest->Stream().IsEOF() ? B_BAD_VALUE : B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h new file mode 100644 index 0000000000..5febb48399 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/RequestInterpreter.h @@ -0,0 +1,54 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef REQUESTINTERPRETER_H +#define REQUESTINTERPRETER_H + + +#include + +#include "FileInfo.h" +#include "NFS4Defs.h" +#include "RPCCallbackRequest.h" + + +class RequestInterpreter { +public: + RequestInterpreter(RPC::CallbackRequest* request); + ~RequestInterpreter(); + + inline uint32 OperationCount(); + inline uint32 Operation(); + + status_t Recall(FileHandle* handle, bool& truncate, + uint32* stateSeq, uint32* stateID); + +private: + uint32 fOperationCount; + uint32 fLastOperation; + + RPC::CallbackRequest* fRequest; +}; + + +inline uint32 +RequestInterpreter::OperationCount() +{ + return fOperationCount; +} + + +inline uint32 +RequestInterpreter::Operation() +{ + fLastOperation = fRequest->Stream().GetUInt(); + return fLastOperation; +} + + +#endif // REQUESTINTERPRETER_H +