nfs4: Renew all owned and used leases
This commit is contained in:
@@ -33,6 +33,7 @@ enum Opcode {
|
|||||||
OpPutRootFH = 24,
|
OpPutRootFH = 24,
|
||||||
OpRead = 25,
|
OpRead = 25,
|
||||||
OpReadDir = 26,
|
OpReadDir = 26,
|
||||||
|
OpRenew = 30,
|
||||||
OpSetClientID = 35,
|
OpSetClientID = 35,
|
||||||
OpSetClientIDConfirm = 36
|
OpSetClientIDConfirm = 36
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
NFS4Server::NFS4Server(RPC::Server* serv)
|
NFS4Server::NFS4Server(RPC::Server* serv)
|
||||||
:
|
:
|
||||||
|
fThreadCancel(true),
|
||||||
|
fLeaseTime(0),
|
||||||
fCIDUseCount(0),
|
fCIDUseCount(0),
|
||||||
fSequenceId(0),
|
fSequenceId(0),
|
||||||
fServer(serv)
|
fServer(serv)
|
||||||
@@ -23,6 +25,12 @@ NFS4Server::NFS4Server(RPC::Server* serv)
|
|||||||
|
|
||||||
NFS4Server::~NFS4Server()
|
NFS4Server::~NFS4Server()
|
||||||
{
|
{
|
||||||
|
fThreadCancel = true;
|
||||||
|
fCIDUseCount = 0;
|
||||||
|
interrupt_thread(fThread);
|
||||||
|
status_t result;
|
||||||
|
wait_for_thread(fThread, &result);
|
||||||
|
|
||||||
mutex_destroy(&fLock);
|
mutex_destroy(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +62,8 @@ NFS4Server::ClientId(uint64 prevId, bool forceNew)
|
|||||||
result = request.Reply().SetClientIDConfirm();
|
result = request.Reply().SetClientIDConfirm();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
_StartRenewing();
|
||||||
}
|
}
|
||||||
|
|
||||||
fCIDUseCount++;
|
fCIDUseCount++;
|
||||||
@@ -72,3 +82,101 @@ NFS4Server::ReleaseCID(uint64 cid)
|
|||||||
mutex_unlock(&fLock);
|
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<NFS4Server*>(ptr);
|
||||||
|
return server->_Renewal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ public:
|
|||||||
|
|
||||||
inline uint32 SequenceId();
|
inline uint32 SequenceId();
|
||||||
private:
|
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;
|
uint64 fClientId;
|
||||||
uint32 fCIDUseCount;
|
uint32 fCIDUseCount;
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
|
|||||||
@@ -323,6 +323,12 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
|||||||
current++;
|
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)) {
|
if (sIsAttrSet(FATTR4_FILEID, bitmap, bcount)) {
|
||||||
values[current].fAttribute = FATTR4_FILEID;
|
values[current].fAttribute = FATTR4_FILEID;
|
||||||
values[current].fData.fValue64 = stream.GetUHyper();
|
values[current].fData.fValue64 = stream.GetUHyper();
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public:
|
|||||||
status_t Read(void* buffer, uint32* size, bool* eof);
|
status_t Read(void* buffer, uint32* size, bool* eof);
|
||||||
status_t ReadDir(uint64* cookie, DirEntry** dirents,
|
status_t ReadDir(uint64* cookie, DirEntry** dirents,
|
||||||
uint32* count, bool* eof);
|
uint32* count, bool* eof);
|
||||||
|
inline status_t Renew();
|
||||||
status_t SetClientID(uint64* clientid, uint64* verifier);
|
status_t SetClientID(uint64* clientid, uint64* verifier);
|
||||||
inline status_t SetClientIDConfirm();
|
inline status_t SetClientIDConfirm();
|
||||||
|
|
||||||
@@ -125,6 +126,13 @@ ReplyInterpreter::PutRootFH()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
ReplyInterpreter::Renew()
|
||||||
|
{
|
||||||
|
return _OperationError(OpRenew);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline status_t
|
inline status_t
|
||||||
ReplyInterpreter::SetClientIDConfirm()
|
ReplyInterpreter::SetClientIDConfirm()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ RequestBuilder::Read(const uint32* id, uint32 stateSeq, uint64 pos, uint32 len)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
||||||
uint32 attr_count)
|
uint32 attrCount)
|
||||||
{
|
{
|
||||||
(void)count;
|
(void)count;
|
||||||
|
|
||||||
@@ -278,7 +278,24 @@ RequestBuilder::ReadDir(uint32 count, uint64* cookie, Attribute* attrs,
|
|||||||
// consider predicting this values basing on count or buffer size
|
// consider predicting this values basing on count or buffer size
|
||||||
fRequest->Stream().AddUInt(0x2000);
|
fRequest->Stream().AddUInt(0x2000);
|
||||||
fRequest->Stream().AddUInt(0x8000);
|
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++;
|
fOpCount++;
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ public:
|
|||||||
status_t Read(const uint32* id, uint32 stateSeq,
|
status_t Read(const uint32* id, uint32 stateSeq,
|
||||||
uint64 pos, uint32 len);
|
uint64 pos, uint32 len);
|
||||||
status_t ReadDir(uint32 count, uint64* cookie,
|
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 SetClientID(const RPC::Server* serv);
|
||||||
status_t SetClientIDConfirm(uint64 id, uint64 ver);
|
status_t SetClientIDConfirm(uint64 id, uint64 ver);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user