mirror of
https://review.haiku-os.org/haiku
synced 2025-02-07 06:16:11 +01:00
nfs4: Add lookup() and get_vnode() hooks
get_vnode() needs a way to retrieve filehandle knowing only inode number. Since NFS4 sever does not provide such services client manages its own mapping between ino_t and filehandles.
This commit is contained in:
parent
aefd79e6a7
commit
7bfa4fe805
56
src/add-ons/kernel/file_systems/nfs4/Filehandle.h
Normal file
56
src/add-ons/kernel/file_systems/nfs4/Filehandle.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, pdziepak@quarnos.org
|
||||
*/
|
||||
#ifndef FILEHANDLE_H
|
||||
#define FILEHANDLE_H
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#define NFS4_FHSIZE 128
|
||||
|
||||
struct Filehandle {
|
||||
uint8 fSize;
|
||||
uint8 fFH[NFS4_FHSIZE];
|
||||
|
||||
inline Filehandle();
|
||||
inline Filehandle(const Filehandle& fh);
|
||||
inline Filehandle& operator=(const Filehandle& fh);
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
Filehandle::Filehandle()
|
||||
:
|
||||
fSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
Filehandle::Filehandle(const Filehandle& fh)
|
||||
:
|
||||
fSize(fh.fSize)
|
||||
{
|
||||
memcpy(fFH, fh.fFH, fSize);
|
||||
}
|
||||
|
||||
|
||||
inline Filehandle&
|
||||
Filehandle::operator=(const Filehandle& fh)
|
||||
{
|
||||
fSize = fh.fSize;
|
||||
memcpy(fFH, fh.fFH, fSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#endif // FILEHANDLE_H
|
||||
|
@ -123,6 +123,23 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Filesystem::GetInode(ino_t id, Inode** _inode)
|
||||
{
|
||||
Filehandle fh;
|
||||
status_t result = fInoIdMap.GetFilehandle(&fh, id);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
Inode* inode = new(std::nothrow)Inode(this, fh, NULL);
|
||||
if (inode == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
*_inode = inode;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Inode*
|
||||
Filesystem::CreateRootInode()
|
||||
{
|
||||
|
@ -9,11 +9,13 @@
|
||||
#define FILESYSTEM_H
|
||||
|
||||
|
||||
#include "InodeIdMap.h"
|
||||
#include "NFS4Defs.h"
|
||||
#include "RPCServer.h"
|
||||
|
||||
|
||||
class Inode;
|
||||
class InodeIdMap;
|
||||
|
||||
class Filesystem {
|
||||
public:
|
||||
@ -21,6 +23,7 @@ public:
|
||||
const char* path, dev_t id);
|
||||
~Filesystem();
|
||||
|
||||
status_t GetInode(ino_t id, Inode** inode);
|
||||
Inode* CreateRootInode();
|
||||
|
||||
inline uint32 FHExpiryType() const;
|
||||
@ -28,6 +31,7 @@ public:
|
||||
inline uint64 GetId();
|
||||
|
||||
inline dev_t DevId() const;
|
||||
inline InodeIdMap* InoIdMap();
|
||||
private:
|
||||
Filesystem();
|
||||
|
||||
@ -39,6 +43,8 @@ private:
|
||||
|
||||
vint64 fId;
|
||||
dev_t fDevId;
|
||||
|
||||
InodeIdMap fInoIdMap;
|
||||
};
|
||||
|
||||
|
||||
@ -63,5 +69,12 @@ Filesystem::DevId() const
|
||||
}
|
||||
|
||||
|
||||
inline InodeIdMap*
|
||||
Filesystem::InoIdMap()
|
||||
{
|
||||
return &fInoIdMap;
|
||||
}
|
||||
|
||||
|
||||
#endif // FILESYSTEM_H
|
||||
|
||||
|
@ -59,6 +59,71 @@ Inode::Inode(Filesystem* fs, const Filehandle &fh, Inode* parent)
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (fType != NF4DIR)
|
||||
return B_NOT_A_DIRECTORY;
|
||||
|
||||
if (!strcmp(name, ".")) {
|
||||
*id = ID();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
RequestBuilder req(ProcCompound);
|
||||
req.PutFH(fHandle);
|
||||
|
||||
if (!strcmp(name, ".."))
|
||||
req.LookUpUp();
|
||||
else
|
||||
req.LookUp(name);
|
||||
|
||||
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 = reply.PutFH();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (!strcmp(name, ".."))
|
||||
result = reply.LookUpUp();
|
||||
else
|
||||
result = reply.LookUp();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
Filehandle fh;
|
||||
result = reply.GetFH(&fh);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
AttrValue* values;
|
||||
uint32 count;
|
||||
result = reply.GetAttr(&values, &count);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (count < 1 || values[0].fAttribute != FATTR4_FILEID) {
|
||||
delete[] values;
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
*id = values[0].fData.fValue64;
|
||||
delete[] values;
|
||||
|
||||
fFilesystem->InoIdMap()->AddEntry(fh, *id);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Inode::Stat(struct stat* st)
|
||||
{
|
||||
|
@ -26,7 +26,9 @@ public:
|
||||
inline ino_t ID() const;
|
||||
inline mode_t Type() const;
|
||||
|
||||
status_t LookUp(const char* name, ino_t* id);
|
||||
status_t Stat(struct stat* st);
|
||||
|
||||
status_t OpenDir(uint64* cookie);
|
||||
status_t ReadDir(void* buffer, uint32 size,
|
||||
uint32* count, uint64* cookie);
|
||||
@ -44,7 +46,7 @@ private:
|
||||
|
||||
Filehandle fHandle;
|
||||
Filesystem* fFilesystem;
|
||||
Inode* fParent;
|
||||
Inode* fParent; // this will cause trouble
|
||||
};
|
||||
|
||||
|
||||
|
51
src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
Normal file
51
src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, pdziepak@quarnos.org
|
||||
*/
|
||||
#ifndef INODEIDMAP_H
|
||||
#define INODEIDMAP_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <util/AVLTreeMap.h>
|
||||
|
||||
#include "Filehandle.h"
|
||||
|
||||
|
||||
class InodeIdMap {
|
||||
public:
|
||||
inline status_t AddEntry(const Filehandle& inode,
|
||||
ino_t id);
|
||||
inline status_t GetFilehandle(Filehandle* fh,
|
||||
ino_t id);
|
||||
|
||||
private:
|
||||
AVLTreeMap<ino_t, Filehandle> fMap;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline status_t
|
||||
InodeIdMap::AddEntry(const Filehandle& inode, ino_t id)
|
||||
{
|
||||
return fMap.Insert(id, inode);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
InodeIdMap::GetFilehandle(Filehandle* fh, ino_t id)
|
||||
{
|
||||
AVLTreeMap<ino_t, Filehandle>::Iterator it = fMap.Find(id);
|
||||
if (!it.HasCurrent())
|
||||
return B_BAD_VALUE;
|
||||
|
||||
*fh = it.Current();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif // INODEIDMAP_H
|
||||
|
@ -13,13 +13,7 @@
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#define NFS4_FHSIZE 128
|
||||
|
||||
struct Filehandle {
|
||||
uint8 fSize;
|
||||
uint8 fFH[NFS4_FHSIZE];
|
||||
};
|
||||
#include "Filehandle.h"
|
||||
|
||||
enum Procedure {
|
||||
ProcNull = 0,
|
||||
@ -31,6 +25,7 @@ enum Opcode {
|
||||
OpGetAttr = 9,
|
||||
OpGetFH = 10,
|
||||
OpLookUp = 15,
|
||||
OpLookUpUp = 16,
|
||||
OpPutFH = 22,
|
||||
OpPutRootFH = 24,
|
||||
OpReadDir = 26
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
status_t GetAttr(AttrValue** attrs, uint32* count);
|
||||
status_t GetFH(Filehandle* fh);
|
||||
inline status_t LookUp();
|
||||
inline status_t LookUpUp();
|
||||
inline status_t PutFH();
|
||||
inline status_t PutRootFH();
|
||||
status_t ReadDir(uint64* cookie, DirEntry** dirents,
|
||||
@ -65,6 +66,13 @@ ReplyInterpreter::LookUp()
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
ReplyInterpreter::LookUpUp()
|
||||
{
|
||||
return _OperationError(OpLookUpUp);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
ReplyInterpreter::PutFH()
|
||||
{
|
||||
|
@ -103,6 +103,21 @@ RequestBuilder::LookUp(const char* name)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::LookUpUp()
|
||||
{
|
||||
if (fProcedure != ProcCompound)
|
||||
return B_BAD_VALUE;
|
||||
if (fRequest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fRequest->Stream().AddUInt(OpLookUpUp);
|
||||
fOpCount++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RequestBuilder::PutFH(const Filehandle& fh)
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
status_t GetAttr(Attribute* attrs, uint32 count);
|
||||
status_t GetFH();
|
||||
status_t LookUp(const char* name);
|
||||
status_t LookUpUp();
|
||||
status_t PutFH(const Filehandle& fh);
|
||||
status_t PutRootFH();
|
||||
status_t ReadDir(uint32 count, uint64* cookie,
|
||||
|
@ -65,6 +65,26 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
nfs4_get_vnode(fs_volume* volume, ino_t id, fs_vnode* vnode, int* _type,
|
||||
uint32* _flags, bool reenter)
|
||||
{
|
||||
Filesystem* fs = reinterpret_cast<Filesystem*>(volume->private_volume);
|
||||
Inode* inode;
|
||||
status_t result = fs->GetInode(id, &inode);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
vnode->ops = &gNFSv4VnodeOps;
|
||||
vnode->private_node = inode;
|
||||
|
||||
*_type = inode->Type();
|
||||
*_flags = 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
nfs4_unmount(fs_volume* volume)
|
||||
{
|
||||
@ -78,6 +98,19 @@ nfs4_unmount(fs_volume* volume)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
nfs4_lookup(fs_volume* volume, fs_vnode* dir, const char* name, ino_t* _id)
|
||||
{
|
||||
Inode* inode = reinterpret_cast<Inode*>(dir->private_node);
|
||||
status_t result = inode->LookUp(name, _id);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
void* ptr;
|
||||
return get_vnode(volume, *_id, &ptr);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
nfs4_put_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter)
|
||||
{
|
||||
@ -183,11 +216,15 @@ nfs4_std_ops(int32 op, ...)
|
||||
|
||||
|
||||
fs_volume_ops gNFSv4VolumeOps = {
|
||||
&nfs4_unmount
|
||||
nfs4_unmount,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
nfs4_get_vnode,
|
||||
};
|
||||
|
||||
fs_vnode_ops gNFSv4VnodeOps = {
|
||||
NULL, // lookup()
|
||||
nfs4_lookup,
|
||||
NULL, // get_vnode_name()
|
||||
nfs4_put_vnode,
|
||||
NULL, // remove_vnode()
|
||||
|
Loading…
x
Reference in New Issue
Block a user