diff --git a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h b/src/add-ons/kernel/file_systems/nfs4/Filehandle.h index 12baf07ef4..cdc149988e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h +++ b/src/add-ons/kernel/file_systems/nfs4/Filehandle.h @@ -9,6 +9,7 @@ #define FILEHANDLE_H +#include #include #include @@ -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 Filehandle::Filehandle() : @@ -52,5 +71,40 @@ Filehandle::operator=(const Filehandle& fh) } +inline +FileInfo::FileInfo() + : + fName(NULL) +{ +} + + +inline +FileInfo::~FileInfo() +{ + free(const_cast(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 diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp index 27c27164af..aa9748c42c 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp @@ -126,12 +126,15 @@ 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); + FileInfo fi; + status_t result = fInoIdMap.GetFileInfo(&fi, id); + if (result == B_ENTRY_NOT_FOUND) + dprintf("NFS4: unknown inode: %llu\n", id); + if (result != B_OK) return result; - Inode* inode = new(std::nothrow)Inode(this, fh); + Inode* inode = new(std::nothrow)Inode(this, fi); if (inode == NULL) return B_NO_MEMORY; @@ -143,6 +146,10 @@ Filesystem::GetInode(ino_t id, Inode** _inode) Inode* 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); } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index fa9091b464..b69e177a84 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -18,15 +18,15 @@ // Creating Inode object from Filehandle probably is not a good idea when // filehandles are volatile. -Inode::Inode(Filesystem* fs, const Filehandle &fh, bool root) +Inode::Inode(Filesystem* fs, const FileInfo &fi) : + fHandle(fi.fFH), fFilesystem(fs), - fRoot(root) + fParentFH(fi.fParent), + fName(strdup(fi.fName)) { - memcpy(&fHandle, &fh, sizeof(fh)); - RequestBuilder req(ProcCompound); - req.PutFH(fh); + req.PutFH(fHandle); Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID }; 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(fName)); +} + + // 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 @@ -116,10 +122,12 @@ Inode::LookUp(const char* name, ino_t* id) delete[] values; 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; + + fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, *id); + return B_OK; } @@ -296,8 +304,6 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size) fileId = fFilesystem->GetId(); } else fileId = values[0].fData.fValue64; - - fFilesystem->InoIdMap()->AddEntry(fh, fileId); 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) { struct dirent* de = reinterpret_cast(buffer + pos); - if (!fRoot) + if (strcmp(fName, "/")) _ReadDirUp(de, pos, size); else _FillDirEntry(de, _FileIdToInoT(fFileId), "..", pos, size); diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 0245e91a79..b21f790f9f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -20,8 +20,8 @@ class Inode { public: - Inode(Filesystem* fs, const Filehandle &fh, - bool root = false); + Inode(Filesystem* fs, const FileInfo& fi); + ~Inode(); inline ino_t ID() const; inline mode_t Type() const; @@ -49,7 +49,8 @@ private: Filehandle fHandle; Filesystem* fFilesystem; - bool fRoot; + Filehandle fParentFH; + const char* fName; }; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h index 3b8bc8d54b..887ab2f98e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h +++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h @@ -17,32 +17,37 @@ class InodeIdMap { public: - inline status_t AddEntry(const Filehandle& inode, - ino_t id); - inline status_t GetFilehandle(Filehandle* fh, - ino_t id); + inline status_t AddEntry(const Filehandle& fh, + const Filehandle& parent, + const char* name, ino_t id); + inline status_t GetFileInfo(FileInfo* fi, ino_t id); private: - AVLTreeMap fMap; + AVLTreeMap fMap; }; 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 -InodeIdMap::GetFilehandle(Filehandle* fh, ino_t id) +InodeIdMap::GetFileInfo(FileInfo* fi, ino_t id) { - AVLTreeMap::Iterator it = fMap.Find(id); + AVLTreeMap::Iterator it = fMap.Find(id); if (!it.HasCurrent()) - return B_BAD_VALUE; + return B_ENTRY_NOT_FOUND; - *fh = it.Current(); + *fi = it.Current(); return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index 023c56735c..085b0b4a1e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -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 nfs4_open_dir(fs_volume* volume, fs_vnode* vnode, void** _cookie) { @@ -269,7 +276,7 @@ fs_vnode_ops gNFSv4VnodeOps = { /* file operations */ NULL, // create() - NULL, // open() + nfs4_open, NULL, // close() NULL, // free_cookie() NULL, // read()