diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.h b/src/add-ons/kernel/file_systems/nfs4/Filesystem.h index 7dac599063..380cbe42ec 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.h @@ -11,7 +11,7 @@ #include "InodeIdMap.h" #include "NFS4Defs.h" -#include "RPCServer.h" +#include "NFS4Server.h" class Inode; @@ -27,7 +27,10 @@ public: Inode* CreateRootInode(); inline uint32 FHExpiryType() const; + inline RPC::Server* Server(); + inline NFS4Server* NFSServer(); + inline uint64 AllocFileId(); inline dev_t DevId() const; @@ -55,6 +58,13 @@ Filesystem::Server() } +inline NFS4Server* +Filesystem::NFSServer() +{ + return reinterpret_cast(fServer->PrivateData()); +} + + inline uint64 Filesystem::AllocFileId() { diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 6e6d77373d..9fc701fa5c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -83,9 +83,6 @@ Inode::~Inode() } -// filesystems that do not provide fileid are currently unsupported -// client will have to be able to create its own mapping between file names -// and made up IDs status_t Inode::LookUp(const char* name, ino_t* id) { @@ -309,39 +306,16 @@ Inode::Stat(struct stat* st) status_t Inode::Open(int mode, OpenFileCookie* cookie) { - cookie->fSeq = 0; + cookie->fClientId = fFilesystem->NFSServer()->ClientId(); Request request(fFilesystem->Server()); - request.Builder().SetClientID(fFilesystem->Server()); - - status_t result = request.Send(); - if (result != B_OK) - return result; - - uint64 id, ver; - result = request.Reply().SetClientID(&id, &ver); - if (result != B_OK) - return result; - - request.Reset(); - request.Builder().SetClientIDConfirm(id, ver); - - result = request.Send(); - if (result != B_OK) - return result; - - result = request.Reply().SetClientIDConfirm(); - if (result != B_OK) - return result; - - request.Reset(); RequestBuilder& req = request.Builder(); req.PutFH(fParentFH); - req.Open(cookie->fSeq, OPEN4_SHARE_ACCESS_READ, id, OPEN4_NOCREATE, fName); - cookie->fSeq++; + req.Open(fFilesystem->NFSServer()->SequenceId(), OPEN4_SHARE_ACCESS_READ, + cookie->fClientId, OPEN4_NOCREATE, fName); - result = request.Send(); + status_t result = request.Send(); if (result != B_OK) return result; @@ -359,8 +333,8 @@ Inode::Open(int mode, OpenFileCookie* cookie) if (confirm) { request.Reset(); req.PutFH(fHandle); - req.OpenConfirm(cookie->fSeq, cookie->fStateId, cookie->fStateSeq); - cookie->fSeq++; + req.OpenConfirm(fFilesystem->NFSServer()->SequenceId(), + cookie->fStateId, cookie->fStateSeq); result = request.Send(); if (result != B_OK) @@ -386,7 +360,8 @@ Inode::Close(OpenFileCookie* cookie) RequestBuilder& req = request.Builder(); req.PutFH(fHandle); - req.Close(cookie->fSeq, cookie->fStateId, cookie->fStateSeq); + req.Close(fFilesystem->NFSServer()->SequenceId(), cookie->fStateId, + cookie->fStateSeq); status_t result = request.Send(); if (result != B_OK) @@ -402,6 +377,8 @@ Inode::Close(OpenFileCookie* cookie) if (result != B_OK) return result; + fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 36f6405fbb..0e99e7cb72 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -19,9 +19,9 @@ struct OpenFileCookie { + uint64 fClientId; uint32 fStateId[3]; uint32 fStateSeq; - uint32 fSeq; }; class Inode { diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile b/src/add-ons/kernel/file_systems/nfs4/Jamfile index e1b56c1186..a5ac6260ff 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 : Filesystem.cpp Inode.cpp kernel_interface.cpp + NFS4Server.cpp ReplyInterpreter.cpp Request.cpp RequestBuilder.cpp diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp new file mode 100644 index 0000000000..8284b85b7f --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ + + +#include "NFS4Server.h" +#include "Request.h" + + +NFS4Server::NFS4Server(RPC::Server* serv) + : + fCIDUseCount(0), + fSequenceId(0), + fServer(serv) +{ + mutex_init(&fLock, NULL); +} + + +NFS4Server::~NFS4Server() +{ + mutex_destroy(&fLock); +} + + +uint64 +NFS4Server::ClientId(uint64 prevId, bool forceNew) +{ + mutex_lock(&fLock); + if ((forceNew && fClientId == prevId) || fCIDUseCount == 0) { + Request request(fServer); + request.Builder().SetClientID(fServer); + + status_t result = request.Send(); + if (result != B_OK) + goto out_unlock; + + uint64 ver; + result = request.Reply().SetClientID(&fClientId, &ver); + if (result != B_OK) + goto out_unlock; + + request.Reset(); + request.Builder().SetClientIDConfirm(fClientId, ver); + + result = request.Send(); + if (result != B_OK) + goto out_unlock; + + result = request.Reply().SetClientIDConfirm(); + if (result != B_OK) + goto out_unlock; + } + + fCIDUseCount++; + +out_unlock: + mutex_unlock(&fLock); + return fClientId; +} + + +void +NFS4Server::ReleaseCID(uint64 cid) +{ + mutex_lock(&fLock); + fCIDUseCount--; + mutex_unlock(&fLock); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h new file mode 100644 index 0000000000..80c43b6237 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef NFS4SERVER_H +#define NFS4SERVER_H + + +#include + +#include "RPCServer.h" + + +class NFS4Server : public RPC::ProgramData { +public: + NFS4Server(RPC::Server* serv); + virtual ~NFS4Server(); + + uint64 ClientId(uint64 prevId = 0, bool forceNew = false); + void ReleaseCID(uint64 cid); + + inline uint32 SequenceId(); +private: + uint64 fClientId; + uint32 fCIDUseCount; + mutex fLock; + + vint32 fSequenceId; + + RPC::Server* fServer; +}; + +uint32 +NFS4Server::SequenceId() +{ + return static_cast(atomic_add(&fSequenceId, 1)); +} + + +#endif // NFS4SERVER_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index 41de2cbcb1..8edb3d84d1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -77,6 +77,7 @@ Server::Server(Connection* conn, ServerAddress* addr) : fConnection(conn), fAddress(addr), + fPrivateData(NULL), fXID(rand() << 1) { _StartListening(); @@ -85,6 +86,8 @@ Server::Server(Connection* conn, ServerAddress* addr) Server::~Server() { + delete fPrivateData; + fThreadCancel = true; fConnection->Disconnect(); interrupt_thread(fThread); @@ -200,7 +203,7 @@ Server::Repair() uint32 Server::_GetXID() { - return (uint32)atomic_add(&fXID, 1); + return static_cast(atomic_add(&fXID, 1)); } @@ -262,7 +265,8 @@ ServerManager::~ServerManager() status_t -ServerManager::Acquire(Server** pserv, uint32 ip, uint16 port, Transport proto) +ServerManager::Acquire(Server** pserv, uint32 ip, uint16 port, Transport proto, + ProgramData* (*createPriv)(Server*)) { status_t result; @@ -301,6 +305,7 @@ ServerManager::Acquire(Server** pserv, uint32 ip, uint16 port, Transport proto) delete conn; return B_NO_MEMORY; } + node->fServer->SetPrivateData(createPriv(node->fServer)); node->fRefCount = 1; node->fLeft = node->fRight = NULL; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h index 3ba5c7fa29..c45765e63e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h @@ -43,6 +43,11 @@ private: }; +class ProgramData { +public: + virtual ~ProgramData() { } +}; + class Server { public: Server(Connection* conn, @@ -63,6 +68,9 @@ public: inline const ServerAddress& ID() const; inline ServerAddress LocalID() const; + inline ProgramData* PrivateData(); + inline void SetPrivateData(ProgramData* priv); + private: inline uint32 _GetXID(); @@ -79,6 +87,8 @@ private: Connection* fConnection; const ServerAddress* fAddress; + ProgramData* fPrivateData; + vint32 fXID; static const bigtime_t kWaitTime = 1000000; }; @@ -118,6 +128,21 @@ Server::LocalID() const } +inline ProgramData* +Server::PrivateData() +{ + return fPrivateData; +} + + +inline void +Server::SetPrivateData(ProgramData* priv) +{ + delete fPrivateData; + fPrivateData = priv; +} + + struct ServerNode { ServerAddress fID; Server* fServer; @@ -133,7 +158,8 @@ public: ~ServerManager(); status_t Acquire(Server** pserv, uint32 ip, uint16 port, - Transport proto); + Transport proto, + ProgramData* (*createPriv)(Server*)); void Release(Server* serv); private: 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 8951a2b0f5..ed922ad062 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -28,6 +28,13 @@ dprintf(const char* format, ...); RPC::ServerManager* gRPCServerManager; +static RPC::ProgramData* +sCreateNFS4Server(RPC::Server* serv) +{ + return new NFS4Server(serv); +} + + static status_t nfs4_mount(fs_volume* volume, const char* device, uint32 flags, const char* args, ino_t* _rootVnodeID) @@ -36,7 +43,8 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags, RPC::Server *server; // hardcoded ip 192.168.1.70 - result = gRPCServerManager->Acquire(&server, 0xc0a80146, 2049, ProtocolUDP); + result = gRPCServerManager->Acquire(&server, 0xc0a80146, 2049, ProtocolUDP, + sCreateNFS4Server); if (result != B_OK) return result;