nfs4: Inodes should know their name and parent's filehandle
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#define FILEHANDLE_H
|
#define FILEHANDLE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
@@ -26,6 +27,24 @@ struct Filehandle {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Complete information needed to identify a file in any situation.
|
||||||
|
// Unfortunately just a filehandle is not enough even when they are persistent
|
||||||
|
// since OPEN requires both parent filehandle and file name (just like LOOKUP).
|
||||||
|
struct FileInfo {
|
||||||
|
Filehandle fFH;
|
||||||
|
|
||||||
|
Filehandle fParent;
|
||||||
|
const char* fName;
|
||||||
|
|
||||||
|
// ... full path may be needed if filehandles are volatile
|
||||||
|
|
||||||
|
inline FileInfo();
|
||||||
|
inline ~FileInfo();
|
||||||
|
inline FileInfo(const FileInfo& fi);
|
||||||
|
inline FileInfo& operator=(const FileInfo& fi);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
Filehandle::Filehandle()
|
Filehandle::Filehandle()
|
||||||
:
|
:
|
||||||
@@ -52,5 +71,40 @@ Filehandle::operator=(const Filehandle& fh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
FileInfo::FileInfo()
|
||||||
|
:
|
||||||
|
fName(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
FileInfo::~FileInfo()
|
||||||
|
{
|
||||||
|
free(const_cast<char*>(fName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline
|
||||||
|
FileInfo::FileInfo(const FileInfo& fi)
|
||||||
|
:
|
||||||
|
fFH(fi.fFH),
|
||||||
|
fParent(fi.fParent),
|
||||||
|
fName(strdup(fi.fName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline FileInfo&
|
||||||
|
FileInfo::operator=(const FileInfo& fi)
|
||||||
|
{
|
||||||
|
fFH = fi.fFH;
|
||||||
|
fParent = fi.fParent;
|
||||||
|
fName = strdup(fi.fName);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // FILEHANDLE_H
|
#endif // FILEHANDLE_H
|
||||||
|
|
||||||
|
|||||||
@@ -126,12 +126,15 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
|||||||
status_t
|
status_t
|
||||||
Filesystem::GetInode(ino_t id, Inode** _inode)
|
Filesystem::GetInode(ino_t id, Inode** _inode)
|
||||||
{
|
{
|
||||||
Filehandle fh;
|
FileInfo fi;
|
||||||
status_t result = fInoIdMap.GetFilehandle(&fh, id);
|
status_t result = fInoIdMap.GetFileInfo(&fi, id);
|
||||||
|
if (result == B_ENTRY_NOT_FOUND)
|
||||||
|
dprintf("NFS4: unknown inode: %llu\n", id);
|
||||||
|
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
Inode* inode = new(std::nothrow)Inode(this, fh);
|
Inode* inode = new(std::nothrow)Inode(this, fi);
|
||||||
if (inode == NULL)
|
if (inode == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -143,6 +146,10 @@ Filesystem::GetInode(ino_t id, Inode** _inode)
|
|||||||
Inode*
|
Inode*
|
||||||
Filesystem::CreateRootInode()
|
Filesystem::CreateRootInode()
|
||||||
{
|
{
|
||||||
return new(std::nothrow)Inode(this, fRootFH, true);
|
FileInfo fi;
|
||||||
|
fi.fFH = fRootFH;
|
||||||
|
fi.fParent = fRootFH;
|
||||||
|
fi.fName = strdup("/");
|
||||||
|
return new(std::nothrow)Inode(this, fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,15 +18,15 @@
|
|||||||
|
|
||||||
// Creating Inode object from Filehandle probably is not a good idea when
|
// Creating Inode object from Filehandle probably is not a good idea when
|
||||||
// filehandles are volatile.
|
// filehandles are volatile.
|
||||||
Inode::Inode(Filesystem* fs, const Filehandle &fh, bool root)
|
Inode::Inode(Filesystem* fs, const FileInfo &fi)
|
||||||
:
|
:
|
||||||
|
fHandle(fi.fFH),
|
||||||
fFilesystem(fs),
|
fFilesystem(fs),
|
||||||
fRoot(root)
|
fParentFH(fi.fParent),
|
||||||
|
fName(strdup(fi.fName))
|
||||||
{
|
{
|
||||||
memcpy(&fHandle, &fh, sizeof(fh));
|
|
||||||
|
|
||||||
RequestBuilder req(ProcCompound);
|
RequestBuilder req(ProcCompound);
|
||||||
req.PutFH(fh);
|
req.PutFH(fHandle);
|
||||||
|
|
||||||
Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID };
|
Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID };
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||||
@@ -59,6 +59,12 @@ Inode::Inode(Filesystem* fs, const Filehandle &fh, bool root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Inode::~Inode()
|
||||||
|
{
|
||||||
|
free(const_cast<char*>(fName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// filesystems that do not provide fileid are currently unsupported
|
// filesystems that do not provide fileid are currently unsupported
|
||||||
// client will have to be able to create its own mapping between file names
|
// client will have to be able to create its own mapping between file names
|
||||||
// and made up IDs
|
// and made up IDs
|
||||||
@@ -116,10 +122,12 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
delete[] values;
|
delete[] values;
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
*id = _FileIdToInoT(values[0].fData.fValue64);
|
|
||||||
fFilesystem->InoIdMap()->AddEntry(fh, values[0].fData.fValue64);
|
|
||||||
|
|
||||||
|
*id = _FileIdToInoT(values[0].fData.fValue64);
|
||||||
delete[] values;
|
delete[] values;
|
||||||
|
|
||||||
|
fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, *id);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,8 +304,6 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
|||||||
fileId = fFilesystem->GetId();
|
fileId = fFilesystem->GetId();
|
||||||
} else
|
} else
|
||||||
fileId = values[0].fData.fValue64;
|
fileId = values[0].fData.fValue64;
|
||||||
|
|
||||||
fFilesystem->InoIdMap()->AddEntry(fh, fileId);
|
|
||||||
|
|
||||||
return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size);
|
return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size);
|
||||||
}
|
}
|
||||||
@@ -326,7 +332,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
if (cookie[0] == 0 && cookie[1] == 1 && count < *_count) {
|
if (cookie[0] == 0 && cookie[1] == 1 && count < *_count) {
|
||||||
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
||||||
|
|
||||||
if (!fRoot)
|
if (strcmp(fName, "/"))
|
||||||
_ReadDirUp(de, pos, size);
|
_ReadDirUp(de, pos, size);
|
||||||
else
|
else
|
||||||
_FillDirEntry(de, _FileIdToInoT(fFileId), "..", pos, size);
|
_FillDirEntry(de, _FileIdToInoT(fFileId), "..", pos, size);
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
class Inode {
|
class Inode {
|
||||||
public:
|
public:
|
||||||
Inode(Filesystem* fs, const Filehandle &fh,
|
Inode(Filesystem* fs, const FileInfo& fi);
|
||||||
bool root = false);
|
~Inode();
|
||||||
|
|
||||||
inline ino_t ID() const;
|
inline ino_t ID() const;
|
||||||
inline mode_t Type() const;
|
inline mode_t Type() const;
|
||||||
@@ -49,7 +49,8 @@ private:
|
|||||||
Filehandle fHandle;
|
Filehandle fHandle;
|
||||||
Filesystem* fFilesystem;
|
Filesystem* fFilesystem;
|
||||||
|
|
||||||
bool fRoot;
|
Filehandle fParentFH;
|
||||||
|
const char* fName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,32 +17,37 @@
|
|||||||
|
|
||||||
class InodeIdMap {
|
class InodeIdMap {
|
||||||
public:
|
public:
|
||||||
inline status_t AddEntry(const Filehandle& inode,
|
inline status_t AddEntry(const Filehandle& fh,
|
||||||
ino_t id);
|
const Filehandle& parent,
|
||||||
inline status_t GetFilehandle(Filehandle* fh,
|
const char* name, ino_t id);
|
||||||
ino_t id);
|
inline status_t GetFileInfo(FileInfo* fi, ino_t id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AVLTreeMap<ino_t, Filehandle> fMap;
|
AVLTreeMap<ino_t, FileInfo> fMap;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
InodeIdMap::AddEntry(const Filehandle& inode, ino_t id)
|
InodeIdMap::AddEntry(const Filehandle& fh, const Filehandle& parent,
|
||||||
|
const char* name, ino_t id)
|
||||||
{
|
{
|
||||||
return fMap.Insert(id, inode);
|
FileInfo fi;
|
||||||
|
fi.fFH = fh;
|
||||||
|
fi.fParent = parent;
|
||||||
|
fi.fName = strdup(name);
|
||||||
|
return fMap.Insert(id, fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
InodeIdMap::GetFilehandle(Filehandle* fh, ino_t id)
|
InodeIdMap::GetFileInfo(FileInfo* fi, ino_t id)
|
||||||
{
|
{
|
||||||
AVLTreeMap<ino_t, Filehandle>::Iterator it = fMap.Find(id);
|
AVLTreeMap<ino_t, FileInfo>::Iterator it = fMap.Find(id);
|
||||||
if (!it.HasCurrent())
|
if (!it.HasCurrent())
|
||||||
return B_BAD_VALUE;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
*fh = it.Current();
|
*fi = it.Current();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,13 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie)
|
||||||
{
|
{
|
||||||
@@ -269,7 +276,7 @@ fs_vnode_ops gNFSv4VnodeOps = {
|
|||||||
|
|
||||||
/* file operations */
|
/* file operations */
|
||||||
NULL, // create()
|
NULL, // create()
|
||||||
NULL, // open()
|
nfs4_open,
|
||||||
NULL, // close()
|
NULL, // close()
|
||||||
NULL, // free_cookie()
|
NULL, // free_cookie()
|
||||||
NULL, // read()
|
NULL, // read()
|
||||||
|
|||||||
Reference in New Issue
Block a user