nfs4: Fix timeout handling code

This commit is contained in:
Pawel Dziepak 2012-06-12 00:38:07 +02:00
parent d8a223873f
commit 0792abe006
7 changed files with 63 additions and 22 deletions

View File

@ -135,9 +135,10 @@ Filesystem::GetInode(ino_t id, Inode** _inode)
if (result != B_OK)
return result;
Inode* inode = new(std::nothrow)Inode(this, fi);
if (inode == NULL)
return B_NO_MEMORY;
Inode* inode;
result = Inode::CreateInode(this, fi, &inode);
if (result != B_OK)
return result;
*_inode = inode;
return B_OK;
@ -151,6 +152,12 @@ Filesystem::CreateRootInode()
fi.fFH = fRootFH;
fi.fParent = fRootFH;
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;
}

View File

@ -15,51 +15,65 @@
#include "Request.h"
Inode::Inode()
{
}
// Creating Inode object from Filehandle probably is not a good idea when
// filehandles are volatile.
Inode::Inode(Filesystem* fs, const FileInfo &fi)
:
fHandle(fi.fFH),
fFilesystem(fs),
fParentFH(fi.fParent),
fName(strdup(fi.fName))
status_t
Inode::CreateInode(Filesystem* fs, const FileInfo &fi, Inode** _inode)
{
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();
req.PutFH(fHandle);
req.PutFH(inode->fHandle);
Attribute attr[] = { FATTR4_TYPE, FATTR4_FILEID };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
status_t result = request.Send();
if (result != B_OK)
return;
return result;
ReplyInterpreter& reply = request.Reply();
result = reply.PutFH();
if (result != B_OK)
return;
return result;
AttrValue* values;
uint32 count;
result = reply.GetAttr(&values, &count);
if (result != B_OK || count < 1)
return;
return result;
if (fi.fFileId == 0) {
if (count < 2 || values[1].fAttribute != FATTR4_FILEID)
fFileId = fs->AllocFileId();
inode->fFileId = fs->AllocFileId();
else
fFileId = values[1].fData.fValue64;
inode->fFileId = values[1].fData.fValue64;
} else
fFileId = fi.fFileId;
inode->fFileId = fi.fFileId;
// FATTR4_TYPE is mandatory
fType = values[0].fData.fValue32;
inode->fType = values[0].fData.fValue32;
delete[] values;
*_inode = inode;
return B_OK;
}

View File

@ -26,7 +26,8 @@ struct OpenFileCookie {
class Inode {
public:
Inode(Filesystem* fs, const FileInfo& fi);
static status_t CreateInode(Filesystem* fs, const FileInfo& fi,
Inode** inode);
~Inode();
inline ino_t ID() const;
@ -47,6 +48,8 @@ public:
uint32* count, uint64* cookie);
private:
Inode();
status_t _ReadDirOnce(DirEntry** dirents, uint32* count,
uint64* cookie, bool* eof);
status_t _FillDirEntry(struct dirent* de, ino_t id,

View File

@ -150,6 +150,8 @@ Server::SendCallAsync(Call* call, Reply** reply, Request** request)
call->SetXID(xid);
req->fXID = xid;
req->fReply = reply;
req->fEvent.Init(&req->fEvent, NULL);
req->fDone = false;
req->fNext = NULL;
fRequests.AddRequest(req);
@ -227,6 +229,7 @@ Server::_Listener()
Request* req = fRequests.FindRequest(reply->GetXID());
if (req != NULL) {
*req->fReply = reply;
req->fDone = true;
req->fEvent.NotifyAll();
} else
delete reply;

View File

@ -22,6 +22,7 @@ namespace RPC {
struct Request {
uint32 fXID;
ConditionVariable fEvent;
bool fDone;
Reply** fReply;
Request* fNext;
@ -86,6 +87,8 @@ private:
inline status_t
Server::WaitCall(Request* request, bigtime_t time)
{
if (request->fDone)
return B_OK;
return request->fEvent.Wait(B_RELATIVE_TIMEOUT, time);
}

View File

@ -35,10 +35,15 @@ Request::_SendUDP()
result = fServer->WaitCall(rpc);
if (result != B_OK) {
int attempts = 1;
while (result != B_OK && attempts++ < kRetryLimit)
while (result != B_OK && attempts++ < kRetryLimit) {
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);
delete rpc;
return result;

View File

@ -50,6 +50,12 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
}
Inode* inode = fs->CreateRootInode();
if (inode == NULL) {
delete fs;
gRPCServerManager->Release(server);
return B_IO_ERROR;
}
volume->private_volume = fs;
volume->ops = &gNFSv4VolumeOps;