nfs4: Add open() hook
This commit is contained in:
parent
8d513ebcb5
commit
2a292557d4
@ -42,6 +42,16 @@ ServerAddress::operator<(const ServerAddress& x)
|
||||
}
|
||||
|
||||
|
||||
ServerAddress&
|
||||
ServerAddress::operator=(const ServerAddress& x)
|
||||
{
|
||||
fAddress = x.fAddress;
|
||||
fPort = x.fPort;
|
||||
fProtocol = x.fProtocol;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(const sockaddr_in& addr, Transport proto, bool markers)
|
||||
:
|
||||
fSock(-1),
|
||||
@ -61,6 +71,23 @@ Connection::~Connection()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Connection::GetLocalID(ServerAddress* addr)
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
status_t result = kgetsockname(fSock, (struct sockaddr*)&saddr, &slen);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
addr->fProtocol = fProtocol;
|
||||
addr->fPort = ntohs(saddr.sin_port);
|
||||
addr->fAddress = ntohl(saddr.sin_addr.s_addr);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Connection::_SendStream(const void* buffer, uint32 size)
|
||||
{
|
||||
|
@ -27,6 +27,8 @@ struct ServerAddress {
|
||||
|
||||
bool operator==(const ServerAddress& x);
|
||||
bool operator<(const ServerAddress& x);
|
||||
|
||||
ServerAddress& operator=(const ServerAddress& x);
|
||||
};
|
||||
|
||||
class Connection {
|
||||
@ -38,6 +40,8 @@ public:
|
||||
inline status_t Send(const void* buffer, uint32 size);
|
||||
inline status_t Receive(void** buffer, uint32* size);
|
||||
|
||||
status_t GetLocalID(ServerAddress* addr);
|
||||
|
||||
status_t Reconnect();
|
||||
void Disconnect();
|
||||
|
||||
|
@ -185,6 +185,70 @@ Inode::Stat(struct stat* st)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::Open(int mode, OpenFileCookie* cookie)
|
||||
{
|
||||
cookie->fSeq = 0;
|
||||
|
||||
RequestBuilder req_setid(ProcCompound);
|
||||
req_setid.SetClientID(fFilesystem->Server());
|
||||
|
||||
RPC::Reply *rpl;
|
||||
fFilesystem->Server()->SendCall(req_setid.Request(), &rpl);
|
||||
ReplyInterpreter setid(rpl);
|
||||
|
||||
uint64 id, ver;
|
||||
status_t result = setid.SetClientID(&id, &ver);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
RequestBuilder req_conf(ProcCompound);
|
||||
req_conf.SetClientIDConfirm(id, ver);
|
||||
|
||||
fFilesystem->Server()->SendCall(req_conf.Request(), &rpl);
|
||||
ReplyInterpreter conf(rpl);
|
||||
|
||||
result = conf.SetClientIDConfirm();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
RequestBuilder req(ProcCompound);
|
||||
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 = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
bool confirm;
|
||||
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (confirm) {
|
||||
RequestBuilder req(ProcCompound);
|
||||
req.PutFH(fHandle);
|
||||
req.OpenConfirm(cookie->fSeq, cookie->fStateId, cookie->fStateSeq);
|
||||
cookie->fSeq++;
|
||||
fFilesystem->Server()->SendCall(req.Request(), &rpl);
|
||||
ReplyInterpreter reply(rpl);
|
||||
|
||||
result = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
result = reply.OpenConfirm(&cookie->fStateSeq);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::OpenDir(uint64* cookie)
|
||||
{
|
||||
|
@ -18,6 +18,12 @@
|
||||
#include "ReplyInterpreter.h"
|
||||
|
||||
|
||||
struct OpenFileCookie {
|
||||
uint32 fStateId[3];
|
||||
uint32 fStateSeq;
|
||||
uint32 fSeq;
|
||||
};
|
||||
|
||||
class Inode {
|
||||
public:
|
||||
Inode(Filesystem* fs, const FileInfo& fi);
|
||||
@ -30,6 +36,8 @@ public:
|
||||
status_t LookUp(const char* name, ino_t* id);
|
||||
status_t Stat(struct stat* st);
|
||||
|
||||
status_t Open(int mode, OpenFileCookie* cookie);
|
||||
|
||||
status_t OpenDir(uint64* cookie);
|
||||
status_t ReadDir(void* buffer, uint32 size,
|
||||
uint32* count, uint64* cookie);
|
||||
|
@ -21,14 +21,18 @@ enum Procedure {
|
||||
};
|
||||
|
||||
enum Opcode {
|
||||
OpAccess = 3,
|
||||
OpGetAttr = 9,
|
||||
OpGetFH = 10,
|
||||
OpLookUp = 15,
|
||||
OpLookUpUp = 16,
|
||||
OpPutFH = 22,
|
||||
OpPutRootFH = 24,
|
||||
OpReadDir = 26
|
||||
OpAccess = 3,
|
||||
OpGetAttr = 9,
|
||||
OpGetFH = 10,
|
||||
OpLookUp = 15,
|
||||
OpLookUpUp = 16,
|
||||
OpOpen = 18,
|
||||
OpOpenConfirm = 20,
|
||||
OpPutFH = 22,
|
||||
OpPutRootFH = 24,
|
||||
OpReadDir = 26,
|
||||
OpSetClientID = 35,
|
||||
OpSetClientIDConfirm = 36
|
||||
};
|
||||
|
||||
enum Access {
|
||||
@ -128,6 +132,21 @@ enum FileHandleExpiryType {
|
||||
FH4_VOL_RENAME = 0x08
|
||||
};
|
||||
|
||||
enum OpenAccess {
|
||||
OPEN4_SHARE_ACCESS_READ = 1,
|
||||
OPEN4_SHARE_ACCESS_WRITE = 2
|
||||
};
|
||||
|
||||
enum OpenCreate {
|
||||
OPEN4_NOCREATE = 0,
|
||||
OPEN4_CREATE = 1
|
||||
};
|
||||
|
||||
enum OpenFlags {
|
||||
OPEN4_RESULT_CONFIRM = 2,
|
||||
OPEN4_RESULT_LOCKTYPE_POSIX = 4
|
||||
};
|
||||
|
||||
enum Errors {
|
||||
NFS4_OK = 0,
|
||||
NFS4ERR_PERM = 1,
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
status_t Repair();
|
||||
|
||||
inline const ServerAddress& ID() const;
|
||||
inline ServerAddress LocalID() const;
|
||||
|
||||
private:
|
||||
inline uint32 _GetXID();
|
||||
@ -80,6 +81,17 @@ Server::ID() const
|
||||
return *fAddress;
|
||||
}
|
||||
|
||||
|
||||
inline ServerAddress
|
||||
Server::LocalID() const
|
||||
{
|
||||
ServerAddress addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
fConnection->GetLocalID(&addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
struct ServerNode {
|
||||
ServerAddress fID;
|
||||
Server* fServer;
|
||||
|
@ -61,7 +61,7 @@ ReplyInterpreter::Access(uint32* supported, uint32* allowed)
|
||||
if (allowed != NULL)
|
||||
*allowed = allow;
|
||||
|
||||
return B_OK;
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +112,55 @@ ReplyInterpreter::GetFH(Filehandle* fh)
|
||||
memcpy(fh->fFH, ptr, size);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyInterpreter::Open(uint32* id, uint32* seq, bool* confirm)
|
||||
{
|
||||
status_t res = _OperationError(OpOpen);
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
*seq = fReply->Stream().GetUInt();
|
||||
id[0] = fReply->Stream().GetUInt();
|
||||
id[1] = fReply->Stream().GetUInt();
|
||||
id[2] = fReply->Stream().GetUInt();
|
||||
|
||||
// change info
|
||||
fReply->Stream().GetBoolean();
|
||||
fReply->Stream().GetUHyper();
|
||||
fReply->Stream().GetUHyper();
|
||||
|
||||
uint32 flags = fReply->Stream().GetUInt();
|
||||
*confirm = (flags & OPEN4_RESULT_CONFIRM) == OPEN4_RESULT_CONFIRM;
|
||||
|
||||
// attrmask
|
||||
uint32 bcount = fReply->Stream().GetUInt();
|
||||
for (uint32 i = 0; i < bcount; i++)
|
||||
fReply->Stream().GetUInt();
|
||||
|
||||
// delegation info
|
||||
fReply->Stream().GetUInt();
|
||||
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyInterpreter::OpenConfirm(uint32* stateSeq)
|
||||
{
|
||||
status_t res = _OperationError(OpOpenConfirm);
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
*stateSeq = fReply->Stream().GetUInt();
|
||||
fReply->Stream().GetUInt();
|
||||
fReply->Stream().GetUInt();
|
||||
fReply->Stream().GetUInt();
|
||||
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -152,7 +200,21 @@ ReplyInterpreter::ReadDir(uint64* cookie, DirEntry** dirents, uint32* _count,
|
||||
*_count = count;
|
||||
*dirents = entries;
|
||||
|
||||
return B_OK;
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReplyInterpreter::SetClientID(uint64* clientid, uint64* verifier)
|
||||
{
|
||||
status_t res = _OperationError(OpSetClientID);
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
*clientid = fReply->Stream().GetUHyper();
|
||||
*verifier = fReply->Stream().GetUHyper();
|
||||
|
||||
return fReply->Stream().IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -230,7 +292,7 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
||||
|
||||
*count = attr_count;
|
||||
*attrs = values;
|
||||
return B_OK;
|
||||
return str.IsEOF() ? B_BAD_VALUE : B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,10 +43,14 @@ public:
|
||||
status_t GetFH(Filehandle* fh);
|
||||
inline status_t LookUp();
|
||||
inline status_t LookUpUp();
|
||||
status_t Open(uint32* id, uint32* seq, bool* confirm);
|
||||
status_t OpenConfirm(uint32* stateSeq);
|
||||
inline status_t PutFH();
|
||||
inline status_t PutRootFH();
|
||||
status_t ReadDir(uint64* cookie, DirEntry** dirents,
|
||||
uint32* count, bool* eof);
|
||||
status_t SetClientID(uint64* clientid, uint64* verifier);
|
||||
inline status_t SetClientIDConfirm();
|
||||
|
||||
private:
|
||||
status_t _DecodeAttrs(XDR::ReadStream& stream, AttrValue** attrs,
|
||||
@ -87,5 +91,12 @@ ReplyInterpreter::PutRootFH()
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
ReplyInterpreter::SetClientIDConfirm()
|
||||
{
|
||||
return _OperationError(OpSetClientIDConfirm);
|
||||
}
|
||||
|
||||
|
||||
#endif // REPLYINTERPRETER_H
|
||||
|
||||
|
@ -118,6 +118,62 @@ RequestBuilder::LookUpUp()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::Open(uint32 seq, uint32 access, uint64 id, OpenCreate oc,
|
||||
const char* name)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpOpen);
|
||||
fRequest->Stream().AddUInt(seq);
|
||||
fRequest->Stream().AddUInt(access);
|
||||
fRequest->Stream().AddUInt(0); // deny none
|
||||
fRequest->Stream().AddUHyper(id);
|
||||
|
||||
char owner[128];
|
||||
int pos = 0;
|
||||
*(uint32*)(owner + pos) = time(NULL);
|
||||
pos += sizeof(uint32);
|
||||
|
||||
*(uint32*)(owner + pos) = find_thread(NULL);
|
||||
pos += sizeof(uint32);
|
||||
|
||||
fRequest->Stream().AddOpaque(owner, pos);
|
||||
|
||||
fRequest->Stream().AddUInt(oc);
|
||||
fRequest->Stream().AddUInt(0); // claim null
|
||||
fRequest->Stream().AddString(name, strlen(name));
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::OpenConfirm(uint32 seq, const uint32* id, uint32 stateSeq)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpOpenConfirm);
|
||||
fRequest->Stream().AddUInt(stateSeq);
|
||||
fRequest->Stream().AddUInt(id[0]);
|
||||
fRequest->Stream().AddUInt(id[1]);
|
||||
fRequest->Stream().AddUInt(id[2]);
|
||||
fRequest->Stream().AddUInt(seq);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::PutFH(const Filehandle& fh)
|
||||
{
|
||||
@ -175,6 +231,63 @@ RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::SetClientID(const RPC::Server* serv)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpSetClientID);
|
||||
uint64 verifier = rand();
|
||||
verifier = verifier << 32 | rand();
|
||||
fRequest->Stream().AddUHyper(verifier);
|
||||
|
||||
char id[128] = "HAIKU:kernel:";
|
||||
int pos = strlen(id);
|
||||
*(uint32*)(id + pos) = serv->ID().fAddress;
|
||||
pos += sizeof(uint32);
|
||||
*(uint16*)(id + pos) = serv->ID().fPort;
|
||||
pos += sizeof(uint16);
|
||||
*(uint16*)(id + pos) = serv->ID().fProtocol;
|
||||
pos += sizeof(uint16);
|
||||
|
||||
*(uint32*)(id + pos) = serv->LocalID().fAddress;
|
||||
pos += sizeof(uint32);
|
||||
|
||||
fRequest->Stream().AddOpaque(id, pos);
|
||||
|
||||
// Callbacks are currently not supported
|
||||
fRequest->Stream().AddUInt(0);
|
||||
fRequest->Stream().AddOpaque(NULL, 0);
|
||||
fRequest->Stream().AddOpaque(NULL, 0);
|
||||
fRequest->Stream().AddUInt(0);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::SetClientIDConfirm(uint64 id, uint64 ver)
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpSetClientIDConfirm);
|
||||
fRequest->Stream().AddUHyper(id);
|
||||
fRequest->Stream().AddUHyper(ver);
|
||||
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
RPC::Call*
|
||||
RequestBuilder::Request()
|
||||
{
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "NFS4Defs.h"
|
||||
#include "RPCCall.h"
|
||||
#include "RPCServer.h"
|
||||
#include "XDR.h"
|
||||
|
||||
|
||||
@ -26,10 +27,16 @@ public:
|
||||
status_t GetFH();
|
||||
status_t LookUp(const char* name);
|
||||
status_t LookUpUp();
|
||||
status_t Open(uint32 seq, uint32 access, uint64 id,
|
||||
OpenCreate oc, const char* name);
|
||||
status_t OpenConfirm(uint32 seq, const uint32* id,
|
||||
uint32 stateSeq);
|
||||
status_t PutFH(const Filehandle& fh);
|
||||
status_t PutRootFH();
|
||||
status_t ReadDir(uint32 count, uint64* cookie,
|
||||
Attribute* attrs, uint32 attr_count);
|
||||
status_t SetClientID(const RPC::Server* serv);
|
||||
status_t SetClientIDConfirm(uint64 id, uint64 ver);
|
||||
|
||||
RPC::Call* Request();
|
||||
|
||||
|
@ -142,7 +142,17 @@ nfs4_read_stat(fs_volume* volume, fs_vnode* vnode, struct stat* stat)
|
||||
static status_t
|
||||
nfs4_open(fs_volume* volume, fs_vnode* vnode, int openMode, void** _cookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
OpenFileCookie* cookie = new OpenFileCookie;
|
||||
if (cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
*_cookie = cookie;
|
||||
|
||||
Inode* inode = reinterpret_cast<Inode*>(vnode->private_node);
|
||||
status_t result = inode->Open(openMode, cookie);
|
||||
if (result != B_OK)
|
||||
delete cookie;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user