diff --git a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h b/src/add-ons/kernel/file_systems/nfs4/Filehandle.h index 3d66aa6027..1aee36ce29 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h +++ b/src/add-ons/kernel/file_systems/nfs4/Filehandle.h @@ -31,6 +31,7 @@ struct Filehandle { // 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 { + uint64 fFileId; Filehandle fFH; Filehandle fParent; @@ -74,6 +75,7 @@ Filehandle::operator=(const Filehandle& fh) inline FileInfo::FileInfo() : + fFileId(0), fName(NULL) { } @@ -89,6 +91,7 @@ FileInfo::~FileInfo() inline FileInfo::FileInfo(const FileInfo& fi) : + fFileId(fi.fFileId), fFH(fi.fFH), fParent(fi.fParent), fName(strdup(fi.fName)) @@ -99,6 +102,7 @@ FileInfo::FileInfo(const FileInfo& fi) inline FileInfo& FileInfo::operator=(const FileInfo& fi) { + fFileId = fi.fFileId; fFH = fi.fFH; fParent = fi.fParent; diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp index 6502c0f2f5..dae44132d8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp @@ -18,7 +18,7 @@ Filesystem::Filesystem() : - fId(0) + fId(1) { } diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.h b/src/add-ons/kernel/file_systems/nfs4/Filesystem.h index d919c269d1..7dac599063 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.h @@ -28,7 +28,7 @@ public: inline uint32 FHExpiryType() const; inline RPC::Server* Server(); - inline uint64 GetId(); + inline uint64 AllocFileId(); inline dev_t DevId() const; inline InodeIdMap* InoIdMap(); @@ -56,7 +56,7 @@ Filesystem::Server() inline uint64 -Filesystem::GetId() +Filesystem::AllocFileId() { return atomic_add64(&fId, 1); } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index a7e92285f7..c0d44ea169 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -48,11 +48,13 @@ Inode::Inode(Filesystem* fs, const FileInfo &fi) if (result != B_OK || count < 1) return; - if (count < 2 || values[1].fAttribute != FATTR4_FILEID) { - // Server does not provide fileid. We need to make something up. - fFileId = fs->GetId(); + if (fi.fFileId == 0) { + if (count < 2 || values[1].fAttribute != FATTR4_FILEID) + fFileId = fs->AllocFileId(); + else + fFileId = values[1].fData.fValue64; } else - fFileId = values[1].fData.fValue64; + fFileId = fi.fFileId; // FATTR4_TYPE is mandatory fType = values[0].fData.fValue32; @@ -124,15 +126,15 @@ Inode::LookUp(const char* name, ino_t* id) if (result != B_OK) return result; - if (count < 1 || values[0].fAttribute != FATTR4_FILEID) { - delete[] values; - return B_UNSUPPORTED; - } - - *id = _FileIdToInoT(values[0].fData.fValue64); + uint64 fileId; + if (count < 1 || values[0].fAttribute != FATTR4_FILEID) + fileId = fFilesystem->AllocFileId(); + else + fileId = values[0].fData.fValue64; delete[] values; - fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, *id); + *id = _FileIdToInoT(fileId); + fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, fileId, *id); return B_OK; } @@ -500,15 +502,19 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size) uint64 fileId; if (count < 1 || values[0].fAttribute != FATTR4_FILEID) { - // Server does not provide fileid. We need to make something up. - fileId = fFilesystem->GetId(); + fileId = fFilesystem->AllocFileId(); } else fileId = values[0].fData.fValue64; return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size); } - +// TODO: Currently inode numbers returned by ReadDir are virtually random. +// Apparently Haiku does not use that information (contrary to inode number +// returned by LookUp) so fixing it can wait until directory caches are +// implemented. +// When directories are cached client should store inode numbers it assigned +// to directroy entries and use them consequently. status_t Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie) { @@ -558,7 +564,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie) if (dirents[i].fAttrCount == 1) id = _FileIdToInoT(dirents[i].fAttrs[0].fData.fValue64); else - id = _FileIdToInoT(fFilesystem->GetId()); + id = _FileIdToInoT(fFilesystem->AllocFileId()); const char* name = dirents[i].fName; if (_FillDirEntry(de, id, name, pos, size) == B_BUFFER_OVERFLOW) { diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h index 887ab2f98e..bf73f0a9d1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h +++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h @@ -19,7 +19,8 @@ class InodeIdMap { public: inline status_t AddEntry(const Filehandle& fh, const Filehandle& parent, - const char* name, ino_t id); + const char* name, uint64 fileId, + ino_t id); inline status_t GetFileInfo(FileInfo* fi, ino_t id); private: @@ -30,9 +31,10 @@ private: inline status_t InodeIdMap::AddEntry(const Filehandle& fh, const Filehandle& parent, - const char* name, ino_t id) + const char* name, uint64 fileId, ino_t id) { FileInfo fi; + fi.fFileId = fileId; fi.fFH = fh; fi.fParent = parent; fi.fName = strdup(name);