nfs4: Fix timeout handling code
This commit is contained in:
@@ -135,9 +135,10 @@ Filesystem::GetInode(ino_t id, Inode** _inode)
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
Inode* inode = new(std::nothrow)Inode(this, fi);
|
Inode* inode;
|
||||||
if (inode == NULL)
|
result = Inode::CreateInode(this, fi, &inode);
|
||||||
return B_NO_MEMORY;
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
*_inode = inode;
|
*_inode = inode;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -151,6 +152,12 @@ Filesystem::CreateRootInode()
|
|||||||
fi.fFH = fRootFH;
|
fi.fFH = fRootFH;
|
||||||
fi.fParent = fRootFH;
|
fi.fParent = fRootFH;
|
||||||
fi.fName = strdup("/");
|
fi.fName = strdup("/");
|
||||||
return new(std::nothrow)Inode(this, fi);
|
|
||||||
|
Inode* inode;
|
||||||
|
status_t result = Inode::CreateInode(this, fi, &inode);
|
||||||
|
if (result == B_OK)
|
||||||
|
return inode;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,51 +15,65 @@
|
|||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
|
Inode::Inode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Creating Inode object from Filehandle probably is not a good idea when
|
// Creating Inode object from Filehandle probably is not a good idea when
|
||||||
// filehandles are volatile.
|
// filehandles are volatile.
|
||||||
Inode::Inode(Filesystem* fs, const FileInfo &fi)
|
status_t
|
||||||
:
|
Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
|
||||||
fHandle(fi.fFH),
|
|
||||||
fFilesystem(fs),
|
|
||||||
fParentFH(fi.fParent),
|
|
||||||
fName(strdup(fi.fName))
|
|
||||||
{
|
{
|
||||||
Request request(fFilesystem->Server());
|
Inode* inode = new(std::nothrow) Inode;
|
||||||
|
if (inode == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
inode->fHandle = fi.fFH;
|
||||||
|
inode->fFilesystem = fs;
|
||||||
|
inode->fParentFH = fi.fParent;
|
||||||
|
inode->fName = strdup(fi.fName);
|
||||||
|
|
||||||
|
Request request(fs->Server());
|
||||||
RequestBuilder& req = request.Builder();
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
req.PutFH(fHandle);
|
req.PutFH(inode->fHandle);
|
||||||
|
|
||||||
Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID };
|
Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID };
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
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)
|
||||||
return;
|
return result;
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
ReplyInterpreter& reply = request.Reply();
|
||||||
|
|
||||||
result = reply.PutFH();
|
result = reply.PutFH();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return;
|
return result;
|
||||||
|
|
||||||
AttrValue* values;
|
AttrValue* values;
|
||||||
uint32 count;
|
uint32 count;
|
||||||
result = reply.GetAttr(&values, &count);
|
result = reply.GetAttr(&values, &count);
|
||||||
if (result != B_OK || count < 1)
|
if (result != B_OK || count < 1)
|
||||||
return;
|
return result;
|
||||||
|
|
||||||
if (fi.fFileId == 0) {
|
if (fi.fFileId == 0) {
|
||||||
if (count < 2 || values[1].fAttribute != FATTR4_FILEID)
|
if (count < 2 || values[1].fAttribute != FATTR4_FILEID)
|
||||||
fFileId = fs->AllocFileId();
|
inode->fFileId = fs->AllocFileId();
|
||||||
else
|
else
|
||||||
fFileId = values[1].fData.fValue64;
|
inode->fFileId = values[1].fData.fValue64;
|
||||||
} else
|
} else
|
||||||
fFileId = fi.fFileId;
|
inode->fFileId = fi.fFileId;
|
||||||
|
|
||||||
// FATTR4_TYPE is mandatory
|
// FATTR4_TYPE is mandatory
|
||||||
fType = values[0].fData.fValue32;
|
inode->fType = values[0].fData.fValue32;
|
||||||
|
|
||||||
delete[] values;
|
delete[] values;
|
||||||
|
|
||||||
|
*_inode = inode;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ struct OpenFileCookie {
|
|||||||
|
|
||||||
class Inode {
|
class Inode {
|
||||||
public:
|
public:
|
||||||
Inode(Filesystem* fs, const FileInfo& fi);
|
static status_t CreateInode(Filesystem* fs, const FileInfo& fi,
|
||||||
|
Inode** inode);
|
||||||
~Inode();
|
~Inode();
|
||||||
|
|
||||||
inline ino_t ID() const;
|
inline ino_t ID() const;
|
||||||
@@ -47,6 +48,8 @@ public:
|
|||||||
uint32* count, uint64* cookie);
|
uint32* count, uint64* cookie);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Inode();
|
||||||
|
|
||||||
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,
|
||||||
|
|||||||
@@ -150,6 +150,8 @@ Server::SendCallAsync(Call* call, Reply** reply, Request** request)
|
|||||||
call->SetXID(xid);
|
call->SetXID(xid);
|
||||||
req->fXID = xid;
|
req->fXID = xid;
|
||||||
req->fReply = reply;
|
req->fReply = reply;
|
||||||
|
req->fEvent.Init(&req->fEvent, NULL);
|
||||||
|
req->fDone = false;
|
||||||
req->fNext = NULL;
|
req->fNext = NULL;
|
||||||
|
|
||||||
fRequests.AddRequest(req);
|
fRequests.AddRequest(req);
|
||||||
@@ -227,6 +229,7 @@ Server::_Listener()
|
|||||||
Request* req = fRequests.FindRequest(reply->GetXID());
|
Request* req = fRequests.FindRequest(reply->GetXID());
|
||||||
if (req != NULL) {
|
if (req != NULL) {
|
||||||
*req->fReply = reply;
|
*req->fReply = reply;
|
||||||
|
req->fDone = true;
|
||||||
req->fEvent.NotifyAll();
|
req->fEvent.NotifyAll();
|
||||||
} else
|
} else
|
||||||
delete reply;
|
delete reply;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace RPC {
|
|||||||
struct Request {
|
struct Request {
|
||||||
uint32 fXID;
|
uint32 fXID;
|
||||||
ConditionVariable fEvent;
|
ConditionVariable fEvent;
|
||||||
|
bool fDone;
|
||||||
Reply** fReply;
|
Reply** fReply;
|
||||||
|
|
||||||
Request* fNext;
|
Request* fNext;
|
||||||
@@ -86,6 +87,8 @@ private:
|
|||||||
inline status_t
|
inline status_t
|
||||||
Server::WaitCall(Request* request, bigtime_t time)
|
Server::WaitCall(Request* request, bigtime_t time)
|
||||||
{
|
{
|
||||||
|
if (request->fDone)
|
||||||
|
return B_OK;
|
||||||
return request->fEvent.Wait(B_RELATIVE_TIMEOUT, time);
|
return request->fEvent.Wait(B_RELATIVE_TIMEOUT, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,15 @@ Request::_SendUDP()
|
|||||||
result = fServer->WaitCall(rpc);
|
result = fServer->WaitCall(rpc);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
int attempts = 1;
|
int attempts = 1;
|
||||||
while (result != B_OK && attempts++ < kRetryLimit)
|
while (result != B_OK && attempts++ < kRetryLimit) {
|
||||||
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
|
result = fServer->ResendCallAsync(fBuilder.Request(), rpc);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
if (attempts == kRetryLimit) {
|
result = fServer->WaitCall(rpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != B_OK) {
|
||||||
fServer->CancelCall(rpc);
|
fServer->CancelCall(rpc);
|
||||||
delete rpc;
|
delete rpc;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Inode* inode = fs->CreateRootInode();
|
Inode* inode = fs->CreateRootInode();
|
||||||
|
if (inode == NULL) {
|
||||||
|
delete fs;
|
||||||
|
gRPCServerManager->Release(server);
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
volume->private_volume = fs;
|
volume->private_volume = fs;
|
||||||
volume->ops = &gNFSv4VolumeOps;
|
volume->ops = &gNFSv4VolumeOps;
|
||||||
|
|||||||
Reference in New Issue
Block a user