nfs4: Partial support for servers not providing FileId

This commit is contained in:
Pawel Dziepak
2012-06-29 02:14:41 +02:00
parent 5945c55ae4
commit e6e9b107de
5 changed files with 32 additions and 20 deletions
@@ -31,6 +31,7 @@ struct Filehandle {
// Unfortunately just a filehandle is not enough even when they are persistent // Unfortunately just a filehandle is not enough even when they are persistent
// since OPEN requires both parent filehandle and file name (just like LOOKUP). // since OPEN requires both parent filehandle and file name (just like LOOKUP).
struct FileInfo { struct FileInfo {
uint64 fFileId;
Filehandle fFH; Filehandle fFH;
Filehandle fParent; Filehandle fParent;
@@ -74,6 +75,7 @@ Filehandle::operator=(const Filehandle& fh)
inline inline
FileInfo::FileInfo() FileInfo::FileInfo()
: :
fFileId(0),
fName(NULL) fName(NULL)
{ {
} }
@@ -89,6 +91,7 @@ FileInfo::~FileInfo()
inline inline
FileInfo::FileInfo(const FileInfo& fi) FileInfo::FileInfo(const FileInfo& fi)
: :
fFileId(fi.fFileId),
fFH(fi.fFH), fFH(fi.fFH),
fParent(fi.fParent), fParent(fi.fParent),
fName(strdup(fi.fName)) fName(strdup(fi.fName))
@@ -99,6 +102,7 @@ FileInfo::FileInfo(const FileInfo& fi)
inline FileInfo& inline FileInfo&
FileInfo::operator=(const FileInfo& fi) FileInfo::operator=(const FileInfo& fi)
{ {
fFileId = fi.fFileId;
fFH = fi.fFH; fFH = fi.fFH;
fParent = fi.fParent; fParent = fi.fParent;
@@ -18,7 +18,7 @@
Filesystem::Filesystem() Filesystem::Filesystem()
: :
fId(0) fId(1)
{ {
} }
@@ -28,7 +28,7 @@ public:
inline uint32 FHExpiryType() const; inline uint32 FHExpiryType() const;
inline RPC::Server* Server(); inline RPC::Server* Server();
inline uint64 GetId(); inline uint64 AllocFileId();
inline dev_t DevId() const; inline dev_t DevId() const;
inline InodeIdMap* InoIdMap(); inline InodeIdMap* InoIdMap();
@@ -56,7 +56,7 @@ Filesystem::Server()
inline uint64 inline uint64
Filesystem::GetId() Filesystem::AllocFileId()
{ {
return atomic_add64(&fId, 1); return atomic_add64(&fId, 1);
} }
+21 -15
View File
@@ -48,11 +48,13 @@ Inode::Inode(Filesystem* fs, const FileInfo &fi)
if (result != B_OK || count < 1) if (result != B_OK || count < 1)
return; return;
if (count < 2 || values[1].fAttribute != FATTR4_FILEID) { if (fi.fFileId == 0) {
// Server does not provide fileid. We need to make something up. if (count < 2 || values[1].fAttribute != FATTR4_FILEID)
fFileId = fs->GetId(); fFileId = fs->AllocFileId();
else
fFileId = values[1].fData.fValue64;
} else } else
fFileId = values[1].fData.fValue64; fFileId = fi.fFileId;
// FATTR4_TYPE is mandatory // FATTR4_TYPE is mandatory
fType = values[0].fData.fValue32; fType = values[0].fData.fValue32;
@@ -124,15 +126,15 @@ Inode::LookUp(const char* name, ino_t* id)
if (result != B_OK) if (result != B_OK)
return result; return result;
if (count < 1 || values[0].fAttribute != FATTR4_FILEID) { uint64 fileId;
delete[] values; if (count < 1 || values[0].fAttribute != FATTR4_FILEID)
return B_UNSUPPORTED; fileId = fFilesystem->AllocFileId();
} else
fileId = values[0].fData.fValue64;
*id = _FileIdToInoT(values[0].fData.fValue64);
delete[] values; delete[] values;
fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, *id); *id = _FileIdToInoT(fileId);
fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, fileId, *id);
return B_OK; return B_OK;
} }
@@ -500,15 +502,19 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
uint64 fileId; uint64 fileId;
if (count < 1 || values[0].fAttribute != FATTR4_FILEID) { if (count < 1 || values[0].fAttribute != FATTR4_FILEID) {
// Server does not provide fileid. We need to make something up. fileId = fFilesystem->AllocFileId();
fileId = fFilesystem->GetId();
} else } else
fileId = values[0].fData.fValue64; fileId = values[0].fData.fValue64;
return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size); 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 status_t
Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie) 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) if (dirents[i].fAttrCount == 1)
id = _FileIdToInoT(dirents[i].fAttrs[0].fData.fValue64); id = _FileIdToInoT(dirents[i].fAttrs[0].fData.fValue64);
else else
id = _FileIdToInoT(fFilesystem->GetId()); id = _FileIdToInoT(fFilesystem->AllocFileId());
const char* name = dirents[i].fName; const char* name = dirents[i].fName;
if (_FillDirEntry(de, id, name, pos, size) == B_BUFFER_OVERFLOW) { if (_FillDirEntry(de, id, name, pos, size) == B_BUFFER_OVERFLOW) {
@@ -19,7 +19,8 @@ class InodeIdMap {
public: public:
inline status_t AddEntry(const Filehandle& fh, inline status_t AddEntry(const Filehandle& fh,
const Filehandle& parent, 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); inline status_t GetFileInfo(FileInfo* fi, ino_t id);
private: private:
@@ -30,9 +31,10 @@ private:
inline status_t inline status_t
InodeIdMap::AddEntry(const Filehandle& fh, const Filehandle& parent, InodeIdMap::AddEntry(const Filehandle& fh, const Filehandle& parent,
const char* name, ino_t id) const char* name, uint64 fileId, ino_t id)
{ {
FileInfo fi; FileInfo fi;
fi.fFileId = fileId;
fi.fFH = fh; fi.fFH = fh;
fi.fParent = parent; fi.fParent = parent;
fi.fName = strdup(name); fi.fName = strdup(name);