nfs4: Add per server NFS4 objects

RPC::Server is now able to store RPC programs data.
NFS4Server objects are currently used mainly for managing client id.
This commit is contained in:
Pawel Dziepak 2012-06-13 01:43:52 +02:00
parent 96e3dbc2d0
commit 6ee3ed0f6f
9 changed files with 184 additions and 39 deletions

View File

@ -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<NFS4Server*>(fServer->PrivateData());
}
inline uint64
Filesystem::AllocFileId()
{

View File

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

View File

@ -19,9 +19,9 @@
struct OpenFileCookie {
uint64 fClientId;
uint32 fStateId[3];
uint32 fStateSeq;
uint32 fSeq;
};
class Inode {

View File

@ -7,6 +7,7 @@ KernelAddon nfs4 :
Filesystem.cpp
Inode.cpp
kernel_interface.cpp
NFS4Server.cpp
ReplyInterpreter.cpp
Request.cpp
RequestBuilder.cpp

View File

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

View File

@ -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 <lock.h>
#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<uint32>(atomic_add(&fSequenceId, 1));
}
#endif // NFS4SERVER_H

View File

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

View File

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

View File

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