nfs4: Partial support for servers not providing FileId
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user