diff --git a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp index dae44132d8..1ac6ddcb15 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Filesystem.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 6d7af636ae..71ec69a34d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 6813ed46ac..36f6405fbb 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -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, diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index 329daec6ec..41de2cbcb1 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h index 8241cd6ee3..3ba5c7fa29 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.h +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.h @@ -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); } diff --git a/src/add-ons/kernel/file_systems/nfs4/Request.cpp b/src/add-ons/kernel/file_systems/nfs4/Request.cpp index 125bdc9aa8..fdf9871086 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Request.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Request.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index d34d25e0df..8951a2b0f5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -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;