diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index f11780ac9a..23a3f70cd9 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -336,32 +336,49 @@ Inode::Stat(struct stat* st) status_t Inode::Open(int mode, OpenFileCookie* cookie) { - cookie->fClientId = fFilesystem->NFSServer()->ClientId(); - - Request request(fFilesystem->Server()); - RequestBuilder& req = request.Builder(); - - req.PutFH(fParentFH); - req.Open(fFilesystem->NFSServer()->SequenceId(), OPEN4_SHARE_ACCESS_READ, - cookie->fClientId, OPEN4_NOCREATE, fName); - - status_t result = request.Send(); - if (result != B_OK) - return result; - - ReplyInterpreter& reply = request.Reply(); - - result = reply.PutFH(); - if (result != B_OK) - return result; - bool confirm; - result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm); - if (result != B_OK) - return result; + status_t result; + do { + cookie->fClientId = fFilesystem->NFSServer()->ClientId(); + + Request request(fFilesystem->Server()); + RequestBuilder& req = request.Builder(); + + req.PutFH(fParentFH); + req.Open(fFilesystem->NFSServer()->SequenceId(), + OPEN4_SHARE_ACCESS_READ, cookie->fClientId, OPEN4_NOCREATE, fName); + + result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter& reply = request.Reply(); + + // server is in grace period, we need to wait + if (reply.NFS4Error() == NFS4ERR_GRACE) { + fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); + snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3, + B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); + continue; + } + + result = reply.PutFH(); + if (result != B_OK) + return result; + + + result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm); + if (result != B_OK) + return result; + + break; + } while (true); if (confirm) { - request.Reset(); + Request request(fFilesystem->Server()); + + RequestBuilder& req = request.Builder(); + req.PutFH(fHandle); req.OpenConfirm(fFilesystem->NFSServer()->SequenceId(), cookie->fStateId, cookie->fStateSeq); @@ -370,6 +387,8 @@ Inode::Open(int mode, OpenFileCookie* cookie) if (result != B_OK) return result; + ReplyInterpreter& reply = request.Reply(); + result = reply.PutFH(); if (result != B_OK) return result; @@ -386,28 +405,39 @@ Inode::Open(int mode, OpenFileCookie* cookie) status_t Inode::Close(OpenFileCookie* cookie) { - Request request(fFilesystem->Server()); - RequestBuilder& req = request.Builder(); + do { + Request request(fFilesystem->Server()); + RequestBuilder& req = request.Builder(); - req.PutFH(fHandle); - req.Close(fFilesystem->NFSServer()->SequenceId(), cookie->fStateId, - cookie->fStateSeq); + req.PutFH(fHandle); + req.Close(fFilesystem->NFSServer()->SequenceId(), cookie->fStateId, + cookie->fStateSeq); - status_t result = request.Send(); - if (result != B_OK) - return result; + status_t result = request.Send(); + if (result != B_OK) + return result; - ReplyInterpreter& reply = request.Reply(); + ReplyInterpreter& reply = request.Reply(); - result = reply.PutFH(); - if (result != B_OK) - return result; + // server is in grace period, we need to wait + if (reply.NFS4Error() == NFS4ERR_GRACE) { + snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3, + B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); + continue; + } - result = reply.Close(); - if (result != B_OK) - return result; + result = reply.PutFH(); + if (result != B_OK) + return result; - fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); + result = reply.Close(); + if (result != B_OK) + return result; + + fFilesystem->NFSServer()->ReleaseCID(cookie->fClientId); + + return B_OK; + } while (true); return B_OK; } @@ -421,28 +451,40 @@ Inode::Read(OpenFileCookie* cookie, off_t pos, void* buffer, size_t* _length) uint32 len = 0; while (size < *_length && !eof) { - Request request(fFilesystem->Server()); - RequestBuilder& req = request.Builder(); + do { + Request request(fFilesystem->Server()); + RequestBuilder& req = request.Builder(); - req.PutFH(fHandle); - req.Read(cookie->fStateId, cookie->fStateSeq, pos + size, - *_length - size); + req.PutFH(fHandle); + req.Read(cookie->fStateId, cookie->fStateSeq, pos + size, + *_length - size); - status_t result = request.Send(); - if (result != B_OK) - return result; + status_t result = request.Send(); + if (result != B_OK) + return result; - ReplyInterpreter& reply = request.Reply(); + ReplyInterpreter& reply = request.Reply(); - result = reply.PutFH(); - if (result != B_OK) - return result; + // server is in grace period, we need to wait + if (reply.NFS4Error() == NFS4ERR_GRACE) { + snooze_etc(fFilesystem->NFSServer()->LeaseTime() / 3, + B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); + continue; + } - result = reply.Read(reinterpret_cast(buffer) + size, &len, &eof); - if (result != B_OK) - return result; + result = reply.PutFH(); + if (result != B_OK) + return result; - size += len; + result = reply.Read(reinterpret_cast(buffer) + size, &len, + &eof); + if (result != B_OK) + return result; + + size += len; + + break; + } while (true); } *_length = size; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index a66c3463bf..506b62e5d4 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -23,6 +23,8 @@ public: void ReleaseCID(uint64 cid); inline uint32 SequenceId(); + + inline uint32 LeaseTime(); private: status_t _GetLeaseTime(); @@ -43,12 +45,22 @@ private: RPC::Server* fServer; }; -uint32 +inline uint32 NFS4Server::SequenceId() { return static_cast(atomic_add(&fSequenceId, 1)); } +inline uint32 +NFS4Server::LeaseTime() +{ + if (fLeaseTime == 0) + _GetLeaseTime(); + + return fLeaseTime; +} + + #endif // NFS4SERVER_H