nfs4: Add Request class for better handling of NFS4 requests

This commit is contained in:
Pawel Dziepak
2012-06-29 02:14:38 +02:00
parent 5310ed9ee1
commit 01d6381d20
11 changed files with 291 additions and 85 deletions
@@ -11,8 +11,7 @@
#include <string.h>
#include "ReplyInterpreter.h"
#include "RequestBuilder.h"
#include "Request.h"
#include "Inode.h"
@@ -33,7 +32,9 @@ status_t
Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
dev_t id)
{
RequestBuilder req(ProcCompound);
Request request(serv);
RequestBuilder& req = request.Builder();
req.PutRootFH();
// Better way of doing this will be needed
@@ -62,11 +63,11 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
Attribute attr[] = { FATTR4_FH_EXPIRE_TYPE };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
RPC::Reply *rpl;
serv->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
status_t result;
ReplyInterpreter& reply = request.Reply();
result = reply.PutRootFH();
if (result != B_OK)
+101 -65
View File
@@ -12,8 +12,7 @@
#include <dirent.h>
#include <string.h>
#include "ReplyInterpreter.h"
#include "RequestBuilder.h"
#include "Request.h"
// Creating Inode object from Filehandle probably is not a good idea when
@@ -25,17 +24,20 @@ Inode::Inode(Filesystem* fs, const FileInfo &fi)
fParentFH(fi.fParent),
fName(strdup(fi.fName))
{
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
RPC::Reply *rpl;
fs->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return;
@@ -79,7 +81,9 @@ Inode::LookUp(const char* name, ino_t* id)
return B_OK;
}
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
if (!strcmp(name, ".."))
@@ -92,11 +96,13 @@ Inode::LookUp(const char* name, ino_t* id)
Attribute attr[] = { FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
status_t result = reply.PutFH();
ReplyInterpreter& reply = request.Reply();
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -135,15 +141,18 @@ Inode::LookUp(const char* name, ino_t* id)
status_t
Inode::Access(int mode)
{
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
req.Access();
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -176,17 +185,20 @@ Inode::Access(int mode)
status_t
Inode::Stat(struct stat* st)
{
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
Attribute attr[] = { FATTR4_SIZE, FATTR4_MODE, FATTR4_NUMLINKS };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -231,34 +243,41 @@ Inode::Open(int mode, OpenFileCookie* cookie)
{
cookie->fSeq = 0;
RequestBuilder req_setid(ProcCompound);
req_setid.SetClientID(fFilesystem->Server());
Request request(fFilesystem->Server());
request.Builder().SetClientID(fFilesystem->Server());
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req_setid.Request(), &rpl);
ReplyInterpreter setid(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
uint64 id, ver;
status_t result = setid.SetClientID(&id, &ver);
result = request.Reply().SetClientID(&id, &ver);
if (result != B_OK)
return result;
RequestBuilder req_conf(ProcCompound);
req_conf.SetClientIDConfirm(id, ver);
request.Reset();
request.Builder().SetClientIDConfirm(id, ver);
fFilesystem->Server()->SendCall(req_conf.Request(), &rpl);
ReplyInterpreter conf(rpl);
result = conf.SetClientIDConfirm();
result = request.Send();
if (result != B_OK)
return result;
RequestBuilder req(ProcCompound);
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++;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
result = reply.PutFH();
if (result != B_OK)
@@ -270,12 +289,14 @@ Inode::Open(int mode, OpenFileCookie* cookie)
return result;
if (confirm) {
RequestBuilder req(ProcCompound);
request.Reset();
req.PutFH(fHandle);
req.OpenConfirm(cookie->fSeq, cookie->fStateId, cookie->fStateSeq);
cookie->fSeq++;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
result = request.Send();
if (result != B_OK)
return result;
result = reply.PutFH();
if (result != B_OK)
@@ -293,15 +314,18 @@ Inode::Open(int mode, OpenFileCookie* cookie)
status_t
Inode::Close(OpenFileCookie* cookie)
{
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
req.Close(cookie->fSeq, cookie->fStateId, cookie->fStateSeq);
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -322,16 +346,19 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
uint32 len = 0;
while (size < *_length && !eof) {
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
req.Read(cookie->fStateId, cookie->fStateSeq, pos + size,
*_length - size);
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -355,15 +382,18 @@ Inode::OpenDir(uint64* cookie)
if (fType != NF4DIR)
return B_NOT_A_DIRECTORY;
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
req.Access();
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -387,17 +417,20 @@ status_t
Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
bool* eof)
{
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
Attribute attr[] = { FATTR4_FILEID };
req.ReadDir(*count, cookie, attr, sizeof(attr) / sizeof(Attribute));
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -431,18 +464,21 @@ Inode::_FillDirEntry(struct dirent* de, ino_t id, const char* name, uint32 pos,
status_t
Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
{
RequestBuilder req(ProcCompound);
Request request(fFilesystem->Server());
RequestBuilder& req = request.Builder();
req.PutFH(fHandle);
req.LookUpUp();
req.GetFH();
Attribute attr[] = { FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
RPC::Reply *rpl;
fFilesystem->Server()->SendCall(req.Request(), &rpl);
ReplyInterpreter reply(rpl);
status_t result = request.Send();
if (result != B_OK)
return result;
ReplyInterpreter& reply = request.Reply();
status_t result;
result = reply.PutFH();
if (result != B_OK)
return result;
@@ -8,6 +8,7 @@ KernelAddon nfs4 :
Inode.cpp
kernel_interface.cpp
ReplyInterpreter.cpp
Request.cpp
RequestBuilder.cpp
RPCAuth.cpp
RPCCall.cpp
@@ -34,9 +34,8 @@ ReplyInterpreter::ReplyInterpreter(RPC::Reply* reply)
:
fReply(reply)
{
fReply->Stream().GetUInt();
fReply->Stream().GetOpaque(NULL);
fReply->Stream().GetUInt();
if (reply != NULL)
_ParseHeader();
}
@@ -46,6 +45,15 @@ ReplyInterpreter::~ReplyInterpreter()
}
void
ReplyInterpreter::_ParseHeader()
{
fReply->Stream().GetUInt();
fReply->Stream().GetOpaque(NULL);
fReply->Stream().GetUInt();
}
status_t
ReplyInterpreter::Access(uint32* supported, uint32* allowed)
{
@@ -330,6 +338,9 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
status_t
ReplyInterpreter::_OperationError(Opcode op)
{
if (fReply == NULL)
return B_NOT_INITIALIZED;
if (fReply->Error() != B_OK || fReply->Stream().IsEOF())
return fReply->Error();
@@ -35,9 +35,12 @@ struct DirEntry {
class ReplyInterpreter {
public:
ReplyInterpreter(RPC::Reply* reply);
ReplyInterpreter(RPC::Reply* reply = NULL);
~ReplyInterpreter();
inline status_t SetTo(RPC::Reply* reply);
inline void Reset();
status_t Access(uint32* supported, uint32* allowed);
status_t Close();
status_t GetAttr(AttrValue** attrs, uint32* count);
@@ -55,6 +58,8 @@ public:
inline status_t SetClientIDConfirm();
private:
void _ParseHeader();
status_t _DecodeAttrs(XDR::ReadStream& stream, AttrValue** attrs,
uint32* count);
status_t _OperationError(Opcode op);
@@ -65,6 +70,29 @@ private:
};
inline status_t
ReplyInterpreter::SetTo(RPC::Reply* _reply)
{
if (fReply != NULL)
return B_DONT_DO_THAT;
fReply = _reply;
if (fReply != NULL)
_ParseHeader();
return B_OK;
}
inline void
ReplyInterpreter::Reset()
{
delete fReply;
fReply = NULL;
}
inline status_t
ReplyInterpreter::LookUp()
{
@@ -0,0 +1,31 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, [email protected]
*/
#include "Request.h"
status_t
Request::Send()
{
RPC::Reply *rpl;
status_t result = fServer->SendCall(fBuilder.Request(), &rpl);
if (result != B_OK)
return result;
return fReply.SetTo(rpl);
}
void
Request::Reset()
{
fBuilder.Reset();
fReply.Reset();
}
@@ -0,0 +1,58 @@
/*
* Copyright 2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Paweł Dziepak, pdziepak@quarnos.org
*/
#ifndef REQUEST_H
#define REQUEST_H
#include "ReplyInterpreter.h"
#include "RequestBuilder.h"
#include "RPCServer.h"
class Request {
public:
inline Request(RPC::Server* serv);
inline RequestBuilder& Builder();
inline ReplyInterpreter& Reply();
status_t Send();
void Reset();
private:
RPC::Server* fServer;
RequestBuilder fBuilder;
ReplyInterpreter fReply;
};
inline
Request::Request(RPC::Server* serv)
:
fServer(serv)
{
}
inline RequestBuilder&
Request::Builder()
{
return fBuilder;
}
inline ReplyInterpreter&
Request::Reply()
{
return fReply;
}
#endif // REQUEST_H
@@ -16,9 +16,27 @@ RequestBuilder::RequestBuilder(Procedure proc)
:
fOpCount(0),
fProcedure(proc),
fRequest(RPC::Call::Create(proc, RPC::Auth::CreateSys(),
RPC::Auth::CreateNone()))
fRequest(NULL)
{
_InitHeader();
}
RequestBuilder::~RequestBuilder()
{
delete fRequest;
}
void
RequestBuilder::_InitHeader()
{
fRequest = RPC::Call::Create(fProcedure, RPC::Auth::CreateSys(),
RPC::Auth::CreateNone());
if (fRequest == NULL)
return;
if (fProcedure == ProcCompound) {
fRequest->Stream().AddOpaque(NULL, 0);
fRequest->Stream().AddUInt(0);
@@ -29,12 +47,6 @@ RequestBuilder::RequestBuilder(Procedure proc)
}
RequestBuilder::~RequestBuilder()
{
delete fRequest;
}
status_t
RequestBuilder::Access()
{
@@ -19,9 +19,11 @@
class RequestBuilder {
public:
RequestBuilder(Procedure proc);
RequestBuilder(Procedure p = ProcCompound);
~RequestBuilder();
inline void Reset(Procedure proc = ProcCompound);
status_t Access();
status_t Close(uint32 seq, const uint32* id,
uint32 stateSeq);
@@ -45,6 +47,8 @@ public:
RPC::Call* Request();
private:
void _InitHeader();
void _AttrBitmap(XDR::WriteStream& stream,
Attribute* attrs, uint32 count);
@@ -57,5 +61,17 @@ private:
};
inline void
RequestBuilder::Reset(Procedure proc)
{
fRequest->Stream().Clear();
fOpCount = 0;
fProcedure = proc;
delete fRequest;
_InitHeader();
}
#endif // REQUESTBUILDER_H
@@ -190,6 +190,17 @@ WriteStream::~WriteStream()
}
void
WriteStream::Clear()
{
free(fBuffer);
fSize = kInitialSize;
fBuffer = reinterpret_cast<uint32*>(malloc(fSize));
fError = B_OK;
fPosition = 0;
}
status_t
WriteStream::InsertUInt(Stream::Position pos, uint32 x)
{
@@ -65,6 +65,7 @@ public:
virtual ~WriteStream();
inline int Size() const;
void Clear();
status_t InsertUInt(Stream::Position pos, uint32 x);