nfs4: Return delegations when asked to
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
#include "NFS4Object.h"
|
||||
|
||||
|
||||
class Delegation : public NFS4Object {
|
||||
class Inode;
|
||||
|
||||
class Delegation : public NFS4Object,
|
||||
public DoublyLinkedListLinkImpl<Delegation> {
|
||||
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
|
||||
|
||||
|
||||
@@ -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()
|
||||
:
|
||||
|
||||
@@ -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<FileHandle, Delegation*>::Iterator it;
|
||||
it = fHandleToDelegation.Find(handle);
|
||||
if (!it.HasCurrent())
|
||||
return NULL;
|
||||
|
||||
return it.Current();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Delegation> fOpenDelegations;
|
||||
mutex fDelegationLock;
|
||||
AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation;
|
||||
|
||||
OpenFileCookie* fOpenFiles;
|
||||
uint32 fOpenCount;
|
||||
mutex fOpenLock;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -228,7 +228,7 @@ Server::GetCallback()
|
||||
{
|
||||
MutexLocker _(fCallbackLock);
|
||||
if (fCallback == NULL) {
|
||||
fCallback = new Callback;
|
||||
fCallback = new(std::nothrow) Callback(this);
|
||||
gRPCCallbackServer->RegisterCallback(fCallback);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ private:
|
||||
|
||||
class ProgramData {
|
||||
public:
|
||||
virtual status_t ProcessCallback(CallbackRequest* request,
|
||||
Connection* connection) = 0;
|
||||
|
||||
virtual ~ProgramData() { }
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
#ifndef REPLYBUILDER_H
|
||||
#define REPLYBUILDER_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <string.h>
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 <SupportDefs.h>
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user