nfs4: Add support for volatile filehandles
This commit is contained in:
@@ -36,8 +36,7 @@ struct FileInfo {
|
|||||||
|
|
||||||
Filehandle fParent;
|
Filehandle fParent;
|
||||||
const char* fName;
|
const char* fName;
|
||||||
|
const char* fPath;
|
||||||
// ... full path may be needed if filehandles are volatile
|
|
||||||
|
|
||||||
inline FileInfo();
|
inline FileInfo();
|
||||||
inline ~FileInfo();
|
inline ~FileInfo();
|
||||||
@@ -76,7 +75,8 @@ inline
|
|||||||
FileInfo::FileInfo()
|
FileInfo::FileInfo()
|
||||||
:
|
:
|
||||||
fFileId(0),
|
fFileId(0),
|
||||||
fName(NULL)
|
fName(NULL),
|
||||||
|
fPath(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +85,7 @@ inline
|
|||||||
FileInfo::~FileInfo()
|
FileInfo::~FileInfo()
|
||||||
{
|
{
|
||||||
free(const_cast<char*>(fName));
|
free(const_cast<char*>(fName));
|
||||||
|
free(const_cast<char*>(fPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +95,8 @@ FileInfo::FileInfo(const FileInfo& fi)
|
|||||||
fFileId(fi.fFileId),
|
fFileId(fi.fFileId),
|
||||||
fFH(fi.fFH),
|
fFH(fi.fFH),
|
||||||
fParent(fi.fParent),
|
fParent(fi.fParent),
|
||||||
fName(strdup(fi.fName))
|
fName(strdup(fi.fName)),
|
||||||
|
fPath(strdup(fi.fPath))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +110,10 @@ FileInfo::operator=(const FileInfo& fi)
|
|||||||
|
|
||||||
free(const_cast<char*>(fName));
|
free(const_cast<char*>(fName));
|
||||||
fName = strdup(fi.fName);
|
fName = strdup(fi.fName);
|
||||||
|
|
||||||
|
free(const_cast<char*>(fPath));
|
||||||
|
fPath = strdup(fi.fPath);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
Filesystem::Filesystem()
|
Filesystem::Filesystem()
|
||||||
:
|
:
|
||||||
|
fPath(NULL),
|
||||||
fId(1)
|
fId(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -25,6 +26,7 @@ Filesystem::Filesystem()
|
|||||||
|
|
||||||
Filesystem::~Filesystem()
|
Filesystem::~Filesystem()
|
||||||
{
|
{
|
||||||
|
free(const_cast<char*>(fPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -60,8 +62,6 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
|||||||
|
|
||||||
req.GetFH();
|
req.GetFH();
|
||||||
req.Access();
|
req.Access();
|
||||||
Attribute attr[] = { FATTR4_FH_EXPIRE_TYPE };
|
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
|
||||||
|
|
||||||
status_t result = request.Send();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
@@ -92,32 +92,12 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
|
|||||||
!= (ACCESS4_READ | ACCESS4_LOOKUP))
|
!= (ACCESS4_READ | ACCESS4_LOOKUP))
|
||||||
return B_PERMISSION_DENIED;
|
return B_PERMISSION_DENIED;
|
||||||
|
|
||||||
AttrValue* values;
|
|
||||||
uint32 count;
|
|
||||||
result = reply.GetAttr(&values, &count);
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (count != 1 || values[0].fAttribute != FATTR4_FH_EXPIRE_TYPE) {
|
|
||||||
delete[] values;
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently, only persistent filehandles are supported. That will be
|
|
||||||
// changed soon.
|
|
||||||
if (values[0].fData.fValue32 != FH4_PERSISTENT) {
|
|
||||||
delete[] values;
|
|
||||||
return B_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Filesystem* fs = new(std::nothrow) Filesystem;
|
Filesystem* fs = new(std::nothrow) Filesystem;
|
||||||
fs->fFHExpiryType = values[0].fData.fValue32;
|
fs->fPath = strdup(fsPath);
|
||||||
memcpy(&fs->fRootFH, &fh, sizeof(Filehandle));
|
memcpy(&fs->fRootFH, &fh, sizeof(Filehandle));
|
||||||
fs->fServer = serv;
|
fs->fServer = serv;
|
||||||
fs->fDevId = id;
|
fs->fDevId = id;
|
||||||
|
|
||||||
delete[] values;
|
|
||||||
|
|
||||||
*pfs = fs;
|
*pfs = fs;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -152,6 +132,7 @@ Filesystem::CreateRootInode()
|
|||||||
fi.fFH = fRootFH;
|
fi.fFH = fRootFH;
|
||||||
fi.fParent = fRootFH;
|
fi.fParent = fRootFH;
|
||||||
fi.fName = strdup("/");
|
fi.fName = strdup("/");
|
||||||
|
fi.fPath = strdup(fPath);
|
||||||
|
|
||||||
Inode* inode;
|
Inode* inode;
|
||||||
status_t result = Inode::CreateInode(this, fi, &inode);
|
status_t result = Inode::CreateInode(this, fi, &inode);
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ public:
|
|||||||
status_t GetInode(ino_t id, Inode** inode);
|
status_t GetInode(ino_t id, Inode** inode);
|
||||||
Inode* CreateRootInode();
|
Inode* CreateRootInode();
|
||||||
|
|
||||||
inline uint32 FHExpiryType() const;
|
|
||||||
|
|
||||||
inline RPC::Server* Server();
|
inline RPC::Server* Server();
|
||||||
inline NFS4Server* NFSServer();
|
inline NFS4Server* NFSServer();
|
||||||
|
|
||||||
@@ -38,7 +36,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Filesystem();
|
Filesystem();
|
||||||
|
|
||||||
uint32 fFHExpiryType;
|
const char* fPath;
|
||||||
|
|
||||||
Filehandle fRootFH;
|
Filehandle fRootFH;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ Inode::Inode()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Creating Inode object from Filehandle probably is not a good idea when
|
|
||||||
// filehandles are volatile.
|
|
||||||
status_t
|
status_t
|
||||||
Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
||||||
{
|
{
|
||||||
@@ -33,7 +31,9 @@ Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
inode->fFilesystem = fs;
|
inode->fFilesystem = fs;
|
||||||
inode->fParentFH = fi.fParent;
|
inode->fParentFH = fi.fParent;
|
||||||
inode->fName = strdup(fi.fName);
|
inode->fName = strdup(fi.fName);
|
||||||
|
inode->fPath = strdup(fi.fPath);
|
||||||
|
|
||||||
|
do {
|
||||||
Request request(fs->Server());
|
Request request(fs->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -48,6 +48,12 @@ Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
inode->_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -74,6 +80,7 @@ Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
|||||||
*_inode = inode;
|
*_inode = inode;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -94,6 +101,7 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -115,6 +123,12 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -145,9 +159,24 @@ Inode::LookUp(const char* name, ino_t* id)
|
|||||||
delete[] values;
|
delete[] values;
|
||||||
|
|
||||||
*id = _FileIdToInoT(fileId);
|
*id = _FileIdToInoT(fileId);
|
||||||
fFilesystem->InoIdMap()->AddEntry(fh, fHandle, name, fileId, *id);
|
|
||||||
|
FileInfo fi;
|
||||||
|
fi.fFileId = fileId;
|
||||||
|
fi.fFH = fh;
|
||||||
|
fi.fParent = fHandle;
|
||||||
|
fi.fName = strdup(name);
|
||||||
|
|
||||||
|
char* path = reinterpret_cast<char*>(malloc(strlen(name) + 2 +
|
||||||
|
strlen(fPath)));
|
||||||
|
strcpy(path, fPath);
|
||||||
|
strcat(path, "/");
|
||||||
|
strcat(path, name);
|
||||||
|
fi.fPath = path;
|
||||||
|
|
||||||
|
fFilesystem->InoIdMap()->AddEntry(fi, *id);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,6 +186,7 @@ Inode::ReadLink(void* buffer, size_t* length)
|
|||||||
if (fType != NF4LNK)
|
if (fType != NF4LNK)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -169,6 +199,12 @@ Inode::ReadLink(void* buffer, size_t* length)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -178,12 +214,14 @@ Inode::ReadLink(void* buffer, size_t* length)
|
|||||||
*length = static_cast<size_t>(size);
|
*length = static_cast<size_t>(size);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::Access(int mode)
|
Inode::Access(int mode)
|
||||||
{
|
{
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -196,6 +234,12 @@ Inode::Access(int mode)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -222,12 +266,14 @@ Inode::Access(int mode)
|
|||||||
return B_NOT_ALLOWED;
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::Stat(struct stat* st)
|
Inode::Stat(struct stat* st)
|
||||||
{
|
{
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -244,6 +290,12 @@ Inode::Stat(struct stat* st)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -308,7 +360,8 @@ Inode::Stat(struct stat* st)
|
|||||||
memset(&st->st_atim, 0, sizeof(timespec));
|
memset(&st->st_atim, 0, sizeof(timespec));
|
||||||
|
|
||||||
if (count >= next && values[next].fAttribute == FATTR4_TIME_CREATE) {
|
if (count >= next && values[next].fAttribute == FATTR4_TIME_CREATE) {
|
||||||
memcpy(&st->st_crtim, values[next].fData.fPointer, sizeof(timespec));
|
memcpy(&st->st_crtim, values[next].fData.fPointer,
|
||||||
|
sizeof(timespec));
|
||||||
next++;
|
next++;
|
||||||
} else
|
} else
|
||||||
memset(&st->st_crtim, 0, sizeof(timespec));
|
memset(&st->st_crtim, 0, sizeof(timespec));
|
||||||
@@ -330,6 +383,7 @@ Inode::Stat(struct stat* st)
|
|||||||
|
|
||||||
delete[] values;
|
delete[] values;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -362,6 +416,12 @@ Inode::Open(int mode, OpenFileCookie* cookie)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// server is in grace period, we need to wait
|
// server is in grace period, we need to wait
|
||||||
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||||
fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId);
|
fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId);
|
||||||
@@ -437,6 +497,12 @@ Inode::Close(OpenFileCookie* cookie)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// server is in grace period, we need to wait
|
// server is in grace period, we need to wait
|
||||||
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||||
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||||
@@ -483,6 +549,12 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// server is in grace period, we need to wait
|
// server is in grace period, we need to wait
|
||||||
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
if (reply.NFS4Error() == NFS4ERR_GRACE) {
|
||||||
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3,
|
||||||
@@ -524,6 +596,7 @@ Inode::OpenDir(uint64* cookie)
|
|||||||
if (fType != NF4DIR)
|
if (fType != NF4DIR)
|
||||||
return B_NOT_A_DIRECTORY;
|
return B_NOT_A_DIRECTORY;
|
||||||
|
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -536,6 +609,12 @@ Inode::OpenDir(uint64* cookie)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -552,6 +631,7 @@ Inode::OpenDir(uint64* cookie)
|
|||||||
cookie[1] = 2;
|
cookie[1] = 2;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -559,6 +639,7 @@ status_t
|
|||||||
Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
||||||
bool* eof)
|
bool* eof)
|
||||||
{
|
{
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -573,11 +654,18 @@ Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, uint64* cookie,
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
return reply.ReadDir(cookie, dirents, count, eof);
|
return reply.ReadDir(cookie, dirents, count, eof);
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -606,6 +694,7 @@ Inode::_FillDirEntry(struct dirent* de, ino_t id, const char* name, uint32 pos,
|
|||||||
status_t
|
status_t
|
||||||
Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
||||||
{
|
{
|
||||||
|
do {
|
||||||
Request request(fFilesystem->Server());
|
Request request(fFilesystem->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
@@ -621,6 +710,12 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
|||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
// filehandle has expired
|
||||||
|
if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) {
|
||||||
|
_LookUpFilehandle();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -647,6 +742,7 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
|
|||||||
fileId = values[0].fData.fValue64;
|
fileId = values[0].fData.fValue64;
|
||||||
|
|
||||||
return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size);
|
return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size);
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Currently inode numbers returned by ReadDir are virtually random.
|
// TODO: Currently inode numbers returned by ReadDir are virtually random.
|
||||||
@@ -726,3 +822,53 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Inode::_LookUpFilehandle()
|
||||||
|
{
|
||||||
|
Request request(fFilesystem->Server());
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
|
req.PutRootFH();
|
||||||
|
|
||||||
|
uint32 lookupCount = 0;
|
||||||
|
char* path = strdup(fPath);
|
||||||
|
char* pathStart = path;
|
||||||
|
char* pathEnd;
|
||||||
|
while (pathStart != NULL) {
|
||||||
|
pathEnd = strpbrk(pathStart, "/");
|
||||||
|
if (pathEnd != NULL)
|
||||||
|
*pathEnd = '\0';
|
||||||
|
|
||||||
|
req.LookUp(pathStart);
|
||||||
|
|
||||||
|
if (pathEnd != NULL && pathEnd[1] != '\0')
|
||||||
|
pathStart = pathEnd + 1;
|
||||||
|
else
|
||||||
|
pathStart = NULL;
|
||||||
|
|
||||||
|
lookupCount++;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
req.GetFH();
|
||||||
|
|
||||||
|
status_t result = request.Send();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
|
result = reply.PutRootFH();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < lookupCount; i++) {
|
||||||
|
result = reply.LookUp();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply.GetFH(&fHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
Inode();
|
Inode();
|
||||||
|
|
||||||
|
status_t _LookUpFilehandle();
|
||||||
|
|
||||||
status_t _ReadDirOnce(DirEntry** dirents, uint32* count,
|
status_t _ReadDirOnce(DirEntry** dirents, uint32* count,
|
||||||
uint64* cookie, bool* eof);
|
uint64* cookie, bool* eof);
|
||||||
status_t _FillDirEntry(struct dirent* de, ino_t id,
|
status_t _FillDirEntry(struct dirent* de, ino_t id,
|
||||||
@@ -78,6 +80,8 @@ private:
|
|||||||
|
|
||||||
Filehandle fParentFH;
|
Filehandle fParentFH;
|
||||||
const char* fName;
|
const char* fName;
|
||||||
|
|
||||||
|
const char* fPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,7 @@
|
|||||||
|
|
||||||
class InodeIdMap {
|
class InodeIdMap {
|
||||||
public:
|
public:
|
||||||
inline status_t AddEntry(const Filehandle& fh,
|
inline status_t AddEntry(const FileInfo& fi,
|
||||||
const Filehandle& parent,
|
|
||||||
const char* name, uint64 fileId,
|
|
||||||
ino_t id);
|
ino_t id);
|
||||||
inline status_t GetFileInfo(FileInfo* fi, ino_t id);
|
inline status_t GetFileInfo(FileInfo* fi, ino_t id);
|
||||||
|
|
||||||
@@ -30,14 +28,8 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
InodeIdMap::AddEntry(const Filehandle& fh, const Filehandle& parent,
|
InodeIdMap::AddEntry(const FileInfo& fi, 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);
|
|
||||||
return fMap.Insert(id, fi);
|
return fMap.Insert(id, fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user