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"
|
#include "NFS4Object.h"
|
||||||
|
|
||||||
|
|
||||||
class Delegation : public NFS4Object {
|
class Inode;
|
||||||
|
|
||||||
|
class Delegation : public NFS4Object,
|
||||||
|
public DoublyLinkedListLinkImpl<Delegation> {
|
||||||
public:
|
public:
|
||||||
Delegation(OpenDelegationData data, Inode* inode,
|
Delegation(const OpenDelegationData& data, Inode* inode,
|
||||||
uint64 clientID);
|
uint64 clientID);
|
||||||
~Delegation();
|
~Delegation();
|
||||||
|
|
||||||
@@ -28,7 +31,12 @@ public:
|
|||||||
|
|
||||||
status_t Reclaim(uint64 newClientID);
|
status_t Reclaim(uint64 newClientID);
|
||||||
|
|
||||||
status_t GiveUp(bool flush);
|
status_t GiveUp(bool truncate);
|
||||||
|
|
||||||
|
inline Inode* GetInode();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
status_t ReturnDelegation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64 fClientID;
|
uint64 fClientID;
|
||||||
@@ -39,5 +47,12 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline Inode*
|
||||||
|
Delegation::GetInode()
|
||||||
|
{
|
||||||
|
return fInode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // DELEGATION_H
|
#endif // DELEGATION_H
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ struct FileHandle {
|
|||||||
inline FileHandle();
|
inline FileHandle();
|
||||||
inline FileHandle(const FileHandle& fh);
|
inline FileHandle(const FileHandle& fh);
|
||||||
inline FileHandle& operator=(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
|
inline
|
||||||
FileInfo::FileInfo()
|
FileInfo::FileInfo()
|
||||||
:
|
:
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ FileSystem::FileSystem()
|
|||||||
|
|
||||||
mutex_init(&fOpenOwnerLock, NULL);
|
mutex_init(&fOpenOwnerLock, NULL);
|
||||||
mutex_init(&fOpenLock, NULL);
|
mutex_init(&fOpenLock, NULL);
|
||||||
|
mutex_init(&fDelegationLock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ FileSystem::~FileSystem()
|
|||||||
{
|
{
|
||||||
NFSServer()->RemoveFileSystem(this);
|
NFSServer()->RemoveFileSystem(this);
|
||||||
|
|
||||||
|
mutex_destroy(&fDelegationLock);
|
||||||
mutex_destroy(&fOpenLock);
|
mutex_destroy(&fOpenLock);
|
||||||
mutex_destroy(&fOpenOwnerLock);
|
mutex_destroy(&fOpenOwnerLock);
|
||||||
|
|
||||||
@@ -308,3 +310,43 @@ FileSystem::RemoveOpenFile(OpenFileCookie* cookie)
|
|||||||
NFSServer()->DecUsage();
|
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 "CacheRevalidator.h"
|
||||||
|
#include "Delegation.h"
|
||||||
#include "InodeIdMap.h"
|
#include "InodeIdMap.h"
|
||||||
#include "NFS4Defs.h"
|
#include "NFS4Defs.h"
|
||||||
#include "NFS4Server.h"
|
#include "NFS4Server.h"
|
||||||
@@ -35,6 +36,12 @@ public:
|
|||||||
void AddOpenFile(OpenFileCookie* cookie);
|
void AddOpenFile(OpenFileCookie* cookie);
|
||||||
void RemoveOpenFile(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 CacheRevalidator& Revalidator();
|
||||||
|
|
||||||
inline bool IsAttrSupported(Attribute attr) const;
|
inline bool IsAttrSupported(Attribute attr) const;
|
||||||
@@ -62,6 +69,10 @@ private:
|
|||||||
|
|
||||||
CacheRevalidator fCacheRevalidator;
|
CacheRevalidator fCacheRevalidator;
|
||||||
|
|
||||||
|
DoublyLinkedList<Delegation> fOpenDelegations;
|
||||||
|
mutex fDelegationLock;
|
||||||
|
AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation;
|
||||||
|
|
||||||
OpenFileCookie* fOpenFiles;
|
OpenFileCookie* fOpenFiles;
|
||||||
uint32 fOpenCount;
|
uint32 fOpenCount;
|
||||||
mutex fOpenLock;
|
mutex fOpenLock;
|
||||||
|
|||||||
@@ -23,11 +23,13 @@
|
|||||||
Inode::Inode()
|
Inode::Inode()
|
||||||
:
|
:
|
||||||
fCache(NULL),
|
fCache(NULL),
|
||||||
|
fDelegation(NULL),
|
||||||
fFileCache(NULL),
|
fFileCache(NULL),
|
||||||
fMaxFileSize(0),
|
fMaxFileSize(0),
|
||||||
fOpenState(NULL),
|
fOpenState(NULL),
|
||||||
fWriteDirty(false)
|
fWriteDirty(false)
|
||||||
{
|
{
|
||||||
|
rw_lock_init(&fDelegationLock, NULL);
|
||||||
mutex_init(&fStateLock, NULL);
|
mutex_init(&fStateLock, NULL);
|
||||||
mutex_init(&fFileCacheLock, NULL);
|
mutex_init(&fFileCacheLock, NULL);
|
||||||
}
|
}
|
||||||
@@ -121,12 +123,16 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
|
|
||||||
Inode::~Inode()
|
Inode::~Inode()
|
||||||
{
|
{
|
||||||
|
if (fDelegation != NULL)
|
||||||
|
RecallDelegation();
|
||||||
|
|
||||||
if (fFileCache != NULL)
|
if (fFileCache != NULL)
|
||||||
file_cache_delete(fFileCache);
|
file_cache_delete(fFileCache);
|
||||||
|
|
||||||
delete fCache;
|
delete fCache;
|
||||||
mutex_destroy(&fStateLock);
|
mutex_destroy(&fStateLock);
|
||||||
mutex_destroy(&fFileCacheLock);
|
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));
|
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();
|
inline uint64 MaxFileSize();
|
||||||
|
|
||||||
|
void SetDelegation(Delegation* delegation);
|
||||||
|
void RecallDelegation(bool truncate = false);
|
||||||
|
|
||||||
status_t LookUp(const char* name, ino_t* id);
|
status_t LookUp(const char* name, ino_t* id);
|
||||||
|
|
||||||
status_t Access(int mode);
|
status_t Access(int mode);
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
{
|
{
|
||||||
MutexLocker _(fStateLock);
|
MutexLocker _(fStateLock);
|
||||||
|
|
||||||
|
OpenDelegationData data;
|
||||||
|
data.fType = OPEN_DELEGATE_NONE;
|
||||||
if (fOpenState == NULL) {
|
if (fOpenState == NULL) {
|
||||||
OpenState* state = new OpenState;
|
OpenState* state = new OpenState;
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
@@ -103,7 +105,7 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
|
|
||||||
state->fInfo = fInfo;
|
state->fInfo = fInfo;
|
||||||
state->fFileSystem = fFileSystem;
|
state->fFileSystem = fFileSystem;
|
||||||
status_t result = OpenFile(state, mode, NULL);
|
status_t result = OpenFile(state, mode, &data);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -112,7 +114,7 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
int newMode = mode & O_RWMASK;
|
int newMode = mode & O_RWMASK;
|
||||||
int oldMode = fOpenState->fMode & O_RWMASK;
|
int oldMode = fOpenState->fMode & O_RWMASK;
|
||||||
if (oldMode != newMode && oldMode != O_RDWR) {
|
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)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
fOpenState->fMode = O_RDWR;
|
fOpenState->fMode = O_RDWR;
|
||||||
@@ -128,6 +130,16 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
|
|
||||||
fFileSystem->AddOpenFile(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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ KernelAddon nfs4 :
|
|||||||
CacheRevalidator.cpp
|
CacheRevalidator.cpp
|
||||||
Cookie.cpp
|
Cookie.cpp
|
||||||
Connection.cpp
|
Connection.cpp
|
||||||
|
Delegation.cpp
|
||||||
DirectoryCache.cpp
|
DirectoryCache.cpp
|
||||||
FileInfo.cpp
|
FileInfo.cpp
|
||||||
FileSystem.cpp
|
FileSystem.cpp
|
||||||
@@ -20,9 +21,11 @@ KernelAddon nfs4 :
|
|||||||
NFS4Object.cpp
|
NFS4Object.cpp
|
||||||
NFS4Server.cpp
|
NFS4Server.cpp
|
||||||
OpenState.cpp
|
OpenState.cpp
|
||||||
|
ReplyBuilder.cpp
|
||||||
ReplyInterpreter.cpp
|
ReplyInterpreter.cpp
|
||||||
Request.cpp
|
Request.cpp
|
||||||
RequestBuilder.cpp
|
RequestBuilder.cpp
|
||||||
|
RequestInterpreter.cpp
|
||||||
RootInode.cpp
|
RootInode.cpp
|
||||||
RPCAuth.cpp
|
RPCAuth.cpp
|
||||||
RPCCall.cpp
|
RPCCall.cpp
|
||||||
|
|||||||
@@ -25,11 +25,16 @@ enum CallbackProcedure {
|
|||||||
CallbackProcCompound = 1
|
CallbackProcCompound = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CallbackOpcode {
|
||||||
|
OpCallbackRecall = 4
|
||||||
|
};
|
||||||
|
|
||||||
enum Opcode {
|
enum Opcode {
|
||||||
OpAccess = 3,
|
OpAccess = 3,
|
||||||
OpClose = 4,
|
OpClose = 4,
|
||||||
OpCommit = 5,
|
OpCommit = 5,
|
||||||
OpCreate = 6,
|
OpCreate = 6,
|
||||||
|
OpDelegReturn = 8,
|
||||||
OpGetAttr = 9,
|
OpGetAttr = 9,
|
||||||
OpGetFH = 10,
|
OpGetFH = 10,
|
||||||
OpLink = 11,
|
OpLink = 11,
|
||||||
|
|||||||
@@ -315,3 +315,71 @@ NFS4Server::_RenewalThreadStart(void* ptr)
|
|||||||
return server->_Renewal();
|
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 <lock.h>
|
||||||
|
|
||||||
|
#include "ReplyBuilder.h"
|
||||||
|
#include "RequestInterpreter.h"
|
||||||
#include "RPCServer.h"
|
#include "RPCServer.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -34,6 +36,12 @@ public:
|
|||||||
uint64 ClientId(uint64 prevId = 0, bool forceNew = false);
|
uint64 ClientId(uint64 prevId = 0, bool forceNew = false);
|
||||||
|
|
||||||
inline uint32 LeaseTime();
|
inline uint32 LeaseTime();
|
||||||
|
|
||||||
|
virtual status_t ProcessCallback(RPC::CallbackRequest* request,
|
||||||
|
Connection* connection);
|
||||||
|
|
||||||
|
status_t CallbackRecall(RequestInterpreter* request,
|
||||||
|
ReplyBuilder* reply);
|
||||||
private:
|
private:
|
||||||
status_t _ReclaimOpen(OpenFileCookie* cookie);
|
status_t _ReclaimOpen(OpenFileCookie* cookie);
|
||||||
status_t _ReclaimLocks(OpenFileCookie* cookie);
|
status_t _ReclaimLocks(OpenFileCookie* cookie);
|
||||||
|
|||||||
@@ -10,15 +10,22 @@
|
|||||||
#include "RPCCallback.h"
|
#include "RPCCallback.h"
|
||||||
|
|
||||||
#include "RPCCallbackRequest.h"
|
#include "RPCCallbackRequest.h"
|
||||||
|
#include "RPCServer.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace RPC;
|
using namespace RPC;
|
||||||
|
|
||||||
|
|
||||||
|
Callback::Callback(Server* server)
|
||||||
|
:
|
||||||
|
fServer(server)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Callback::EnqueueRequest(CallbackRequest* request, Connection* connection)
|
Callback::EnqueueRequest(CallbackRequest* request, Connection* connection)
|
||||||
{
|
{
|
||||||
dprintf("GOT A CALLBACK REQUEST %x\n", (int)request->XID());
|
return fServer->PrivateData()->ProcessCallback(request, connection);
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,12 @@
|
|||||||
namespace RPC {
|
namespace RPC {
|
||||||
|
|
||||||
class CallbackRequest;
|
class CallbackRequest;
|
||||||
|
class Server;
|
||||||
|
|
||||||
class Callback {
|
class Callback {
|
||||||
public:
|
public:
|
||||||
|
Callback(Server* server);
|
||||||
|
|
||||||
inline void SetID(int32 id);
|
inline void SetID(int32 id);
|
||||||
inline int32 ID();
|
inline int32 ID();
|
||||||
|
|
||||||
@@ -25,6 +28,7 @@ public:
|
|||||||
Connection* connection);
|
Connection* connection);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Server* fServer;
|
||||||
int32 fID;
|
int32 fID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,10 @@ CallbackRequest::CallbackRequest(void *buffer, int size)
|
|||||||
|
|
||||||
fProcedure = fStream.GetUInt();
|
fProcedure = fStream.GetUInt();
|
||||||
|
|
||||||
|
fStream.GetUInt();
|
||||||
fStream.GetOpaque(NULL);
|
fStream.GetOpaque(NULL);
|
||||||
|
|
||||||
|
fStream.GetUInt();
|
||||||
fStream.GetOpaque(NULL);
|
fStream.GetOpaque(NULL);
|
||||||
|
|
||||||
if (fProcedure == CallbackProcCompound) {
|
if (fProcedure == CallbackProcCompound) {
|
||||||
@@ -54,6 +57,9 @@ CallbackRequest::CallbackRequest(void *buffer, int size)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fID = fStream.GetUInt();
|
fID = fStream.GetUInt();
|
||||||
|
|
||||||
|
fRPCError = SUCCESS;
|
||||||
|
fError = B_OK;
|
||||||
} else if (fProcedure == CallbackProcNull) {
|
} else if (fProcedure == CallbackProcNull) {
|
||||||
fRPCError = SUCCESS;
|
fRPCError = SUCCESS;
|
||||||
fError = B_OK;
|
fError = B_OK;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ CallbackServer::CallbackServer()
|
|||||||
fConnectionList(NULL),
|
fConnectionList(NULL),
|
||||||
fListener(NULL),
|
fListener(NULL),
|
||||||
fThreadRunning(false),
|
fThreadRunning(false),
|
||||||
fCallbackArray(NULL),
|
//fCallbackArray(NULL),
|
||||||
fArraySize(0),
|
fArraySize(0),
|
||||||
fFreeSlot(-1)
|
fFreeSlot(-1)
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,7 @@ CallbackServer::~CallbackServer()
|
|||||||
{
|
{
|
||||||
StopServer();
|
StopServer();
|
||||||
|
|
||||||
free(fCallbackArray);
|
//free(fCallbackArray);
|
||||||
rw_lock_destroy(&fArrayLock);
|
rw_lock_destroy(&fArrayLock);
|
||||||
mutex_destroy(&fThreadLock);
|
mutex_destroy(&fThreadLock);
|
||||||
mutex_destroy(&fConnectionLock);
|
mutex_destroy(&fConnectionLock);
|
||||||
@@ -68,7 +68,7 @@ CallbackServer::RegisterCallback(Callback* callback)
|
|||||||
for (uint32 i = fArraySize; i < newSize; i++)
|
for (uint32 i = fArraySize; i < newSize; i++)
|
||||||
array[i].fNext = i + 1;
|
array[i].fNext = i + 1;
|
||||||
|
|
||||||
array[fArraySize * 2 - 1].fNext = -1;
|
array[newSize - 1].fNext = -1;
|
||||||
|
|
||||||
fCallbackArray = array;
|
fCallbackArray = array;
|
||||||
fFreeSlot = fArraySize;
|
fFreeSlot = fArraySize;
|
||||||
@@ -240,7 +240,7 @@ CallbackServer::ConnectionThread(ConnectionEntry* entry)
|
|||||||
if (request == NULL || request->Error() != B_OK) {
|
if (request == NULL || request->Error() != B_OK) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
continue;
|
continue;
|
||||||
} else if (request != NULL) {
|
} else if (request != NULL && request->Error() != B_OK) {
|
||||||
reply = CallbackReply::Create(request->XID(), request->RPCError());
|
reply = CallbackReply::Create(request->XID(), request->RPCError());
|
||||||
if (reply != NULL) {
|
if (reply != NULL) {
|
||||||
connection->Send(reply->Stream().Buffer(),
|
connection->Send(reply->Stream().Buffer(),
|
||||||
@@ -251,7 +251,6 @@ CallbackServer::ConnectionThread(ConnectionEntry* entry)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (request->Procedure()) {
|
switch (request->Procedure()) {
|
||||||
case CallbackProcCompound:
|
case CallbackProcCompound:
|
||||||
GetCallback(request->ID())->EnqueueRequest(request, connection);
|
GetCallback(request->ID())->EnqueueRequest(request, connection);
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ Server::GetCallback()
|
|||||||
{
|
{
|
||||||
MutexLocker _(fCallbackLock);
|
MutexLocker _(fCallbackLock);
|
||||||
if (fCallback == NULL) {
|
if (fCallback == NULL) {
|
||||||
fCallback = new Callback;
|
fCallback = new(std::nothrow) Callback(this);
|
||||||
gRPCCallbackServer->RegisterCallback(fCallback);
|
gRPCCallbackServer->RegisterCallback(fCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ private:
|
|||||||
|
|
||||||
class ProgramData {
|
class ProgramData {
|
||||||
public:
|
public:
|
||||||
|
virtual status_t ProcessCallback(CallbackRequest* request,
|
||||||
|
Connection* connection) = 0;
|
||||||
|
|
||||||
virtual ~ProgramData() { }
|
virtual ~ProgramData() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <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 Close();
|
||||||
status_t Commit();
|
status_t Commit();
|
||||||
status_t Create(uint64* before, uint64* after, bool& atomic);
|
status_t Create(uint64* before, uint64* after, bool& atomic);
|
||||||
|
inline status_t DelegReturn();
|
||||||
status_t GetAttr(AttrValue** attrs, uint32* count);
|
status_t GetAttr(AttrValue** attrs, uint32* count);
|
||||||
status_t GetFH(FileHandle* fh);
|
status_t GetFH(FileHandle* fh);
|
||||||
status_t Link(uint64* before, uint64* after, bool& atomic);
|
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
|
inline status_t
|
||||||
ReplyInterpreter::LookUp()
|
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
|
status_t
|
||||||
RequestBuilder::GetAttr(Attribute* attrs, uint32 count)
|
RequestBuilder::GetAttr(Attribute* attrs, uint32 count)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public:
|
|||||||
status_t Create(FileType type, const char* name,
|
status_t Create(FileType type, const char* name,
|
||||||
AttrValue* attr, uint32 count,
|
AttrValue* attr, uint32 count,
|
||||||
const char* path = NULL);
|
const char* path = NULL);
|
||||||
|
status_t DelegReturn(const uint32* id, uint32 seq);
|
||||||
status_t GetAttr(Attribute* attrs, uint32 count);
|
status_t GetAttr(Attribute* attrs, uint32 count);
|
||||||
status_t GetFH();
|
status_t GetFH();
|
||||||
status_t Link(const char* name);
|
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