From 27a291de54f614424392492632152093a84e2810 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Wed, 13 Jun 2012 02:38:51 +0200 Subject: [PATCH] nfs4: Renew all owned and used leases --- .../kernel/file_systems/nfs4/NFS4Defs.h | 1 + .../kernel/file_systems/nfs4/NFS4Server.cpp | 108 ++++++++++++++++++ .../kernel/file_systems/nfs4/NFS4Server.h | 10 ++ .../file_systems/nfs4/ReplyInterpreter.cpp | 6 + .../file_systems/nfs4/ReplyInterpreter.h | 8 ++ .../file_systems/nfs4/RequestBuilder.cpp | 21 +++- .../kernel/file_systems/nfs4/RequestBuilder.h | 3 +- 7 files changed, 154 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 8ded674387..c8b71121e8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -33,6 +33,7 @@ enum Opcode { OpPutRootFH = 24, OpRead = 25, OpReadDir = 26, + OpRenew = 30, OpSetClientID = 35, OpSetClientIDConfirm = 36 }; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 8284b85b7f..3bf1b5d3b5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -13,6 +13,8 @@ NFS4Server::NFS4Server(RPC::Server* serv) : + fThreadCancel(true), + fLeaseTime(0), fCIDUseCount(0), fSequenceId(0), fServer(serv) @@ -23,6 +25,12 @@ NFS4Server::NFS4Server(RPC::Server* serv) NFS4Server::~NFS4Server() { + fThreadCancel = true; + fCIDUseCount = 0; + interrupt_thread(fThread); + status_t result; + wait_for_thread(fThread, &result); + mutex_destroy(&fLock); } @@ -54,6 +62,8 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew) result = request.Reply().SetClientIDConfirm(); if (result != B_OK) goto out_unlock; + + _StartRenewing(); } fCIDUseCount++; @@ -72,3 +82,101 @@ NFS4Server::ReleaseCID(uint64 cid) mutex_unlock(&fLock); } + +status_t +NFS4Server::_GetLeaseTime() +{ + Request request(fServer); + request.Builder().PutRootFH(); + Attribute attr[] = { FATTR4_LEASE_TIME }; + request.Builder().GetAttr(attr, sizeof(attr) / sizeof(Attribute)); + + status_t result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter& reply = request.Reply(); + + result = reply.PutRootFH(); + if (result != B_OK) + return result; + + AttrValue* values; + uint32 count; + result = reply.GetAttr(&values, &count); + if (result != B_OK) + return result; + + // FATTR4_LEASE_TIM is mandatory + if (count < 1 || values[0].fAttribute != FATTR4_LEASE_TIME) { + delete[] values; + return B_BAD_VALUE; + } + + fLeaseTime = values[0].fData.fValue32 * 1000000; + + return B_OK; +} + + +status_t +NFS4Server::_StartRenewing() +{ + if (!fThreadCancel) + return B_OK; + + + if (fLeaseTime == 0) { + status_t result = _GetLeaseTime(); + if (result != B_OK) + return result; + } + + fThreadCancel = false; + fThread = spawn_kernel_thread(&NFS4Server::_RenewalThreadStart, + "NFSv4 Renewal", B_NORMAL_PRIORITY, this); + if (fThread < B_OK) + return fThread; + + status_t result = resume_thread(fThread); + if (result != B_OK) { + kill_thread(fThread); + return result; + } + + return B_OK; +} + + +status_t +NFS4Server::_Renewal() +{ + while (!fThreadCancel) { + // TODO: operations like OPEN, READ, CLOSE, etc also renew leases + snooze_etc(fLeaseTime - 2, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT + | B_CAN_INTERRUPT); + mutex_lock(&fLock); + if (fCIDUseCount == 0) { + fThreadCancel = true; + mutex_unlock(&fLock); + return B_OK; + } + + Request request(fServer); + request.Builder().Renew(fClientId); + request.Send(); + + mutex_unlock(&fLock); + } + + return B_OK; +} + + +status_t +NFS4Server::_RenewalThreadStart(void* ptr) +{ + NFS4Server* server = reinterpret_cast(ptr); + return server->_Renewal(); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index 80c43b6237..a66c3463bf 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -24,6 +24,16 @@ public: inline uint32 SequenceId(); private: + status_t _GetLeaseTime(); + + status_t _StartRenewing(); + status_t _Renewal(); + static status_t _RenewalThreadStart(void* ptr); + thread_id fThread; + bool fThreadCancel; + + uint32 fLeaseTime; + uint64 fClientId; uint32 fCIDUseCount; mutex fLock; diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index d38f6d542f..ece60c05c8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -323,6 +323,12 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs, current++; } + if (sIsAttrSet(FATTR4_LEASE_TIME, bitmap, bcount)) { + values[current].fAttribute = FATTR4_LEASE_TIME; + values[current].fData.fValue32 = stream.GetUInt(); + current++; + } + if (sIsAttrSet(FATTR4_FILEID, bitmap, bcount)) { values[current].fAttribute = FATTR4_FILEID; values[current].fData.fValue64 = stream.GetUHyper(); diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 1531fe73e2..c513b81ca7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -58,6 +58,7 @@ public: status_t Read(void* buffer, uint32* size, bool* eof); status_t ReadDir(uint64* cookie, DirEntry** dirents, uint32* count, bool* eof); + inline status_t Renew(); status_t SetClientID(uint64* clientid, uint64* verifier); inline status_t SetClientIDConfirm(); @@ -125,6 +126,13 @@ ReplyInterpreter::PutRootFH() } +inline status_t +ReplyInterpreter::Renew() +{ + return _OperationError(OpRenew); +} + + inline status_t ReplyInterpreter::SetClientIDConfirm() { diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 414322fd3a..b7dc398eba 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -262,7 +262,7 @@ RequestBuilder::Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len) status_t RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs, - uint32 attr_count) + uint32 attrCount) { (void)count; @@ -278,7 +278,24 @@ RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs, // consider predicting this values basing on count or buffer size fRequest->Stream().AddUInt(0x2000); fRequest->Stream().AddUInt(0x8000); - _AttrBitmap(fRequest->Stream(), attrs, attr_count); + _AttrBitmap(fRequest->Stream(), attrs, attrCount); + + fOpCount++; + + return B_OK; +} + + +status_t +RequestBuilder::Renew(uint64 clientId) +{ + if (fProcedure != ProcCompound) + return B_BAD_VALUE; + if (fRequest == NULL) + return B_NO_MEMORY; + + fRequest->Stream().AddUInt(OpRenew); + fRequest->Stream().AddUHyper(clientId); fOpCount++; diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 86f5070e71..130c053511 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -40,7 +40,8 @@ public: status_t Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len); status_t ReadDir(uint32 count, uint64* cookie, - Attribute* attrs, uint32 attr_count); + Attribute* attrs, uint32 attrCount); + status_t Renew(uint64 clientId); status_t SetClientID(const RPC::Server* serv); status_t SetClientIDConfirm(uint64 id, uint64 ver);